# MewCP Docs
> Complete documentation for Large Language Models
---
## Document: Getting Started
Go from a new MewCP account to calling your first MCP tool.
URL: /mewcp/getting-started
# Getting Started
## What you will build
By the end of this tutorial you will have Claude Desktop connected to MewCP, with your Google Calendar available as a tool, and you will have asked Claude a question it answers by calling that tool.
**Time:** about 5 minutes.
**What you need:**
- A MewCP account ([sign up](https://mewcp.com))
- Claude Desktop installed ([download](https://claude.ai/download))
- Node.js installed (needed by the `mcp-remote` bridge Claude Desktop uses)
---
1. **Connect an app**
1. Log in to the [MewCP dashboard](https://mewcp.com/dashboard)
1. Go to **Servers** and pick **Google Calendar**
1. Click **Connect account** and sign in with Google
That is the only place credentials are handled. Your connection is encrypted and stored in a secure vault, and you never paste a token into your client.
Connect as many apps as you like, now or later. Every one of them is reachable through the same setup below.
1. **Get your MewCP Key**
1. In the dashboard go to **API Keys**
1. Copy your **MewCP Key**
Your key looks like: `mcp_live_7df44e73e8cd42bb...`
Keep this key safe. It is how your client proves it is you.
1. **Connect Claude Desktop**
Open your Claude Desktop config file:
| Platform | Path |
| -------- | ----------------------------------------------------------------- |
| macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |
| Windows | `%APPDATA%\Claude\claude_desktop_config.json` |
Replace `your_key_here` with the key you just copied:
```json
{
"mcpServers": {
"mewcp": {
"command": "npx",
"args": [
"-y",
"mcp-remote@latest",
"https://gateway.mewcp.com/personal/mcp",
"--header",
"Authorization: Bearer ${MEWCP_KEY}"
],
"env": {
"MEWCP_KEY": "your_key_here"
}
}
}
}
```
That is the whole config, and it does not change when you connect more apps.
Save the file and **restart Claude Desktop**.
You will see a tools icon appear in the chat panel confirming MewCP is connected.
1. **Ask for something** 🚀
Open a new Claude Desktop chat and type:
```
What is on my calendar tomorrow?
```
Claude will find the right tool, call it against your connected Google account, and answer:
> You have two events tomorrow: a team standup at 9:30am and a design review at 2pm.
That is it. You have made your first tool call through MewCP.
---
## How MewCP works
**One URL, every app.**
Your **personal toolset** is the set of apps you have connected. It has a single endpoint, `https://gateway.mewcp.com/personal/mcp`. Connect another app in the dashboard and it is available straight away, with no config change and no restart.
When your client connects, it does not see hundreds of tools. It sees four:
| Tool | What it does |
| --------------- | ------------------------------------------------ |
| `search` | Find tools by keyword across every connected app |
| `get_schema` | Get the parameters for the tools it picked |
| `list_accounts` | List the accounts connected for one app |
| `call_tool` | Run the tool |
Your agent uses them in that order, which is why you can ask in plain language and still get the right call. Keeping the tool list small is what keeps the agent accurate as the number of connected apps grows.
If you have connected two accounts for the same app, `list_accounts` shows both and the agent picks one by its alias.
### Your credentials stay with MewCP
Connected credentials are encrypted at rest in a secure vault. They are decrypted and injected into the upstream request only at the moment a tool is called, and never travel to your client, your agent, or the model. Your config holds one MewCP Key and nothing else.
Expired access is refreshed for you. If an app is not connected yet, or access was revoked, the call comes back with a link to hand to the user instead of failing quietly.
---
## What's next
- **Other clients**: Connect via [VS Code and Cursor](/mewcp/connect/vscode-cursor), [TypeScript](/mewcp/connect/typescript), [Python](/mewcp/connect/python), or [Codex](/mewcp/connect/codex)
- **AI agent frameworks**: Wire MewCP into [Google ADK](/mewcp/connect-agents/google-adk), [LangChain](/mewcp/connect-agents/langchain-python), [CrewAI](/mewcp/connect-agents/crewai), and more
- **B2B / multi-user apps**: Use the [MewCP Auth API](/mewcp-auth) to manage credentials for your audience
---
## Document: OpenAI Agents SDK
Connect MewCP to an OpenAI Agents SDK agent.
URL: /mewcp/connect-agents/openai-agents
# OpenAI Agents SDK
## Install
```bash
pip install openai-agents
```
---
## Connect
```python
import asyncio
from agents.mcp import MCPServerStreamableHttp
MEWCP_KEY = "YOUR_MEWCP_KEY"
async def main():
async with MCPServerStreamableHttp(
name="mewcp",
params={
"url": "https://gateway.mewcp.com/personal/mcp",
"headers": {"Authorization": f"Bearer {MEWCP_KEY}"},
"timeout": 30,
},
cache_tools_list=True,
) as server:
tools = await server.list_tools()
print("Available tools:", [t.name for t in tools])
# -> ["search", "get_schema", "list_accounts", "call_tool"]
asyncio.run(main())
```
You get four tools rather than the tools of each app. Your agent uses them to reach every app you have connected. See [How MewCP works](/mewcp/getting-started#how-mewcp-works).
---
## Call a tool directly
```python
result = await server.call_tool(
tool_name="call_tool",
arguments={
"server_maskedId": "google-calendar",
"tool_name": "list_events",
"args": {
"calendar_id": "primary",
"time_min": "2026-01-15T00:00:00Z",
"time_max": "2026-01-16T00:00:00Z",
},
},
)
print(result.content)
```
If you have connected more than one account for the same app, add `"alias": "work"` to select one.
---
## Use with an agent
```python
import asyncio
from agents import Agent, Runner
from agents.mcp import MCPServerStreamableHttp
async def main():
async with MCPServerStreamableHttp(
name="mewcp",
params={
"url": "https://gateway.mewcp.com/personal/mcp",
"headers": {"Authorization": f"Bearer {MEWCP_KEY}"},
},
) as server:
agent = Agent(
name="Assistant",
instructions="You are a helpful assistant with access to the user's connected apps.",
mcp_servers=[server],
)
result = await Runner.run(agent, "What is on my calendar tomorrow?")
print(result.final_output)
asyncio.run(main())
```
The agent will call `search` to find the calendar tool, `get_schema` for its parameters, then `call_tool` to run it.
---
## Where to find your values
| Value | Where to get it |
| ---------------- | --------------------- |
| `YOUR_MEWCP_KEY` | Dashboard -> API Keys |
| Connected apps | Dashboard -> Servers |
---
## Document: LangChain TypeScript
Connect MewCP to a LangChain TypeScript agent.
URL: /mewcp/connect-agents/langchain-typescript
# LangChain TypeScript
## Install
```bash
npm install @langchain/mcp-adapters
```
---
## Connect
```typescript
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
const MEWCP_KEY = "YOUR_MEWCP_KEY";
async function main() {
const client = new MultiServerMCPClient({
mcpServers: {
mewcp: {
url: "https://gateway.mewcp.com/personal/mcp",
headers: {
Authorization: `Bearer ${MEWCP_KEY}`,
},
},
},
});
const tools = await client.getTools();
console.log(
"Available tools:",
tools.map((t) => t.name),
);
// -> ["search", "get_schema", "list_accounts", "call_tool"]
await client.close();
}
main();
```
You get four tools rather than the tools of each app. Your agent uses them to reach every app you have connected. See [How MewCP works](/mewcp/getting-started#how-mewcp-works).
---
## Call a tool directly
```typescript
const callTool = tools.find((t) => t.name === "call_tool")!;
const result = await callTool.invoke({
server_maskedId: "google-calendar",
tool_name: "list_events",
args: {
calendar_id: "primary",
time_min: "2026-01-15T00:00:00Z",
time_max: "2026-01-16T00:00:00Z",
},
});
console.log(result);
```
If you have connected more than one account for the same app, add `alias: "work"` to select one.
---
## Use with a LangChain agent
Hand all four tools to the agent and let it work out the rest:
```typescript
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
import { ChatOpenAI } from "@langchain/openai";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { HumanMessage } from "@langchain/core/messages";
async function main() {
const client = new MultiServerMCPClient({
mcpServers: {
mewcp: {
url: "https://gateway.mewcp.com/personal/mcp",
headers: { Authorization: `Bearer ${MEWCP_KEY}` },
},
},
});
const tools = await client.getTools();
const model = new ChatOpenAI({ model: "gpt-4o" });
const agent = createReactAgent({ llm: model, tools });
const result = await agent.invoke({
messages: [new HumanMessage("What is on my calendar tomorrow?")],
});
console.log(result.messages.at(-1)?.content);
await client.close();
}
main();
```
The agent will call `search` to find the calendar tool, `get_schema` for its parameters, then `call_tool` to run it.
---
## Where to find your values
| Value | Where to get it |
| ---------------- | --------------------- |
| `YOUR_MEWCP_KEY` | Dashboard -> API Keys |
| Connected apps | Dashboard -> Servers |
---
## Document: LangChain Python
Connect MewCP to a LangChain Python agent.
URL: /mewcp/connect-agents/langchain-python
# LangChain Python
## Install
```bash
pip install langchain-mcp-adapters
```
---
## Connect
```python
import asyncio
from langchain_mcp_adapters.client import MultiServerMCPClient
MEWCP_KEY = "YOUR_MEWCP_KEY"
async def main():
async with MultiServerMCPClient(
{
"mewcp": {
"transport": "streamable_http",
"url": "https://gateway.mewcp.com/personal/mcp",
"headers": {"Authorization": f"Bearer {MEWCP_KEY}"},
}
}
) as client:
tools = await client.get_tools()
print("Available tools:", [t.name for t in tools])
# -> ["search", "get_schema", "list_accounts", "call_tool"]
asyncio.run(main())
```
> Note: `transport` value is `"streamable_http"` (underscore).
You get four tools rather than the tools of each app. Your agent uses them to reach every app you have connected. See [How MewCP works](/mewcp/getting-started#how-mewcp-works).
---
## Call a tool directly
```python
call_tool = next(t for t in tools if t.name == "call_tool")
result = await call_tool.ainvoke(
{
"server_maskedId": "google-calendar",
"tool_name": "list_events",
"args": {
"calendar_id": "primary",
"time_min": "2026-01-15T00:00:00Z",
"time_max": "2026-01-16T00:00:00Z",
},
}
)
print(result)
```
If you have connected more than one account for the same app, add `"alias": "work"` to select one.
---
## Use with a LangChain agent
Hand all four tools to the agent and let it work out the rest:
```python
import asyncio
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
async def main():
async with MultiServerMCPClient(
{
"mewcp": {
"transport": "streamable_http",
"url": "https://gateway.mewcp.com/personal/mcp",
"headers": {"Authorization": f"Bearer {MEWCP_KEY}"},
}
}
) as client:
tools = await client.get_tools()
model = ChatOpenAI(model="gpt-4o")
agent = create_react_agent(model, tools)
result = await agent.ainvoke(
{"messages": [{"role": "user", "content": "What is on my calendar tomorrow?"}]}
)
print(result["messages"][-1].content)
asyncio.run(main())
```
The agent will call `search` to find the calendar tool, `get_schema` for its parameters, then `call_tool` to run it.
---
## Where to find your values
| Value | Where to get it |
| ---------------- | --------------------- |
| `YOUR_MEWCP_KEY` | Dashboard -> API Keys |
| Connected apps | Dashboard -> Servers |
---
## Document: Google ADK
Connect MewCP to a Google Agent Development Kit agent.
URL: /mewcp/connect-agents/google-adk
# Google ADK
## Install
```bash
pip install google-adk
```
---
## Connect
```python
import asyncio
from google.adk.tools.mcp_tool import MCPToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams
MEWCP_KEY = "YOUR_MEWCP_KEY"
async def main():
toolset = MCPToolset(
connection_params=StreamableHTTPConnectionParams(
url="https://gateway.mewcp.com/personal/mcp",
headers={"Authorization": f"Bearer {MEWCP_KEY}"},
)
)
tools = await toolset.get_tools()
print("Available tools:", [t.name for t in tools])
# -> ["search", "get_schema", "list_accounts", "call_tool"]
await toolset.close()
asyncio.run(main())
```
You get four tools rather than the tools of each app. Your agent uses them to reach every app you have connected. See [How MewCP works](/mewcp/getting-started#how-mewcp-works).
---
## Call a tool directly
```python
call_tool = next(t for t in tools if t.name == "call_tool")
result = await call_tool.run_async(
args={
"server_maskedId": "google-calendar",
"tool_name": "list_events",
"args": {
"calendar_id": "primary",
"time_min": "2026-01-15T00:00:00Z",
"time_max": "2026-01-16T00:00:00Z",
},
},
tool_context=None,
)
print(result)
```
If you have connected more than one account for the same app, add `"alias": "work"` to select one.
---
## Use with an LLM agent
Pass the toolset to an `LlmAgent` and ADK calls tools automatically based on the model's decisions:
```python
from google.adk.agents import LlmAgent
from google.adk.tools.mcp_tool import MCPToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams
toolset = MCPToolset(
connection_params=StreamableHTTPConnectionParams(
url="https://gateway.mewcp.com/personal/mcp",
headers={"Authorization": f"Bearer {MEWCP_KEY}"},
)
)
agent = LlmAgent(
model="gemini-2.0-flash",
name="assistant",
instruction="You are a helpful assistant with access to the user's connected apps.",
tools=[toolset],
)
```
---
## B2B: per-user credential routing
To route calls for different audience members, use a `header_provider` callable instead of static headers:
```python
MCPToolset(
connection_params=StreamableHTTPConnectionParams(
url="https://gateway.mewcp.com/personal/mcp",
),
header_provider=lambda ctx: {
"Authorization": f"Bearer {MEWCP_KEY}",
"x-mewcp-enduser-id": ctx.session.state["user_id"],
},
)
```
---
## Where to find your values
| Value | Where to get it |
| ---------------- | --------------------- |
| `YOUR_MEWCP_KEY` | Dashboard -> API Keys |
| Connected apps | Dashboard -> Servers |
---
## Document: CrewAI
Connect MewCP to a CrewAI agent.
URL: /mewcp/connect-agents/crewai
# CrewAI
## Install
```bash
pip install crewai "crewai-tools[mcp]"
```
---
## Connect
`MCPServerAdapter` wraps MCP tools as CrewAI-compatible tools. It requires a context manager to manage the connection lifecycle:
```python
from crewai_tools import MCPServerAdapter
MEWCP_KEY = "YOUR_MEWCP_KEY"
server_params = {
"url": "https://gateway.mewcp.com/personal/mcp",
"transport": "streamable-http",
"headers": {"Authorization": f"Bearer {MEWCP_KEY}"},
}
with MCPServerAdapter(server_params) as mcp_tools:
print("Available tools:", [t.name for t in mcp_tools])
# -> ["search", "get_schema", "list_accounts", "call_tool"]
```
> Note: `transport` must be `"streamable-http"` (hyphenated).
You get four tools rather than the tools of each app. Your agent uses them to reach every app you have connected. See [How MewCP works](/mewcp/getting-started#how-mewcp-works).
---
## Call a tool directly
```python
with MCPServerAdapter(server_params) as mcp_tools:
call_tool = next(t for t in mcp_tools if t.name == "call_tool")
result = call_tool.run({
"server_maskedId": "google-calendar",
"tool_name": "list_events",
"args": {
"calendar_id": "primary",
"time_min": "2026-01-15T00:00:00Z",
"time_max": "2026-01-16T00:00:00Z",
},
})
print(result)
```
If you have connected more than one account for the same app, add `"alias": "work"` to select one.
---
## Use with a CrewAI agent
Hand all four tools to the agent and let it work out the rest:
```python
from crewai import Agent, Task, Crew
from crewai_tools import MCPServerAdapter
server_params = {
"url": "https://gateway.mewcp.com/personal/mcp",
"transport": "streamable-http",
"headers": {"Authorization": f"Bearer {MEWCP_KEY}"},
}
with MCPServerAdapter(server_params) as mcp_tools:
agent = Agent(
role="Assistant",
goal="Answer questions using the user's connected apps",
backstory="Expert at finding and using the right tool for the job.",
tools=list(mcp_tools),
verbose=True,
)
task = Task(
description="Check what is on my calendar tomorrow and summarise the day.",
expected_output="A short summary of tomorrow's schedule.",
agent=agent,
)
crew = Crew(agents=[agent], tasks=[task])
crew.kickoff()
```
---
## Where to find your values
| Value | Where to get it |
| ---------------- | --------------------- |
| `YOUR_MEWCP_KEY` | Dashboard -> API Keys |
| Connected apps | Dashboard -> Servers |
---
## Document: Claude SDK
Connect MewCP to Claude via the Anthropic Python SDK.
URL: /mewcp/connect-agents/claude-sdk
# Claude SDK
## Install
```bash
pip install anthropic
```
---
## How it works
The Anthropic SDK's MCP connector is different from other frameworks. Rather than giving you a direct MCP client, it lets the **Anthropic API** act as the MCP client on your behalf. You attach the MCP server to your API call, Claude decides which tools to call, and the API handles the MCP protocol round-trip.
You cannot call `list_tools()` or `call_tool()` imperatively. The model drives all tool use.
That suits MewCP well. Claude sees four tools, `search`, `get_schema`, `list_accounts`, and `call_tool`, and uses them to reach every app you have connected. See [How MewCP works](/mewcp/getting-started#how-mewcp-works).
---
## Example
```python
import anthropic
MEWCP_KEY = "YOUR_MEWCP_KEY"
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-opus-5",
max_tokens=2048,
messages=[
{
"role": "user",
"content": "What is on my calendar tomorrow?",
}
],
mcp_servers=[
{
"type": "url",
"url": "https://gateway.mewcp.com/personal/mcp",
"name": "mewcp",
"authorization_token": MEWCP_KEY,
}
],
betas=["mcp-client-2025-11-20"],
)
# The response may contain text blocks and mcp_tool_result blocks
for block in response.content:
if hasattr(block, "text"):
print(block.text)
```
One server entry covers every app you have connected. Connecting another app in the dashboard needs no change here.
---
## Choosing an account
When you have connected more than one account for the same app, say which one you mean in the prompt. Claude will call `list_accounts` and pick it by alias:
```python
messages=[
{
"role": "user",
"content": "Check my work Gmail for anything from the design team.",
}
]
```
---
## Important notes
- `authorization_token` sends the value as `Authorization: Bearer `. Do not put `Bearer` in the value.
- The beta header is `"mcp-client-2025-11-20"`. The older `mcp-client-2025-04-04` is deprecated.
- Only MCP **tools** are supported via this connector. Prompts and resources are not exposed.
- The server URL must be `https://`.
---
## Where to find your values
| Value | Where to get it |
| ---------------- | --------------------- |
| `YOUR_MEWCP_KEY` | Dashboard -> API Keys |
| Connected apps | Dashboard -> Servers |
---
## Document: VS Code & Cursor
Connect MewCP to VS Code or Cursor.
URL: /mewcp/connect/vscode-cursor
# VS Code & Cursor
## Prerequisites
- VS Code with GitHub Copilot extension, or Cursor
- A MewCP Key, see [Authentication](/mewcp/authentication)
- At least one app connected in the dashboard under **Servers**
---
## VS Code
Open **Command Palette** (`Cmd+Shift+P` / `Ctrl+Shift+P`) and select **Open User Settings (JSON)**.
Add MewCP under the `mcp` key. VS Code will prompt you for the key securely the first time:
```json
{
"mcp": {
"inputs": [
{
"type": "promptString",
"id": "MEWCP_KEY",
"description": "MewCP Key",
"password": true
}
],
"servers": {
"mewcp": {
"type": "http",
"url": "https://gateway.mewcp.com/personal/mcp",
"headers": {
"Authorization": "Bearer ${input:MEWCP_KEY}"
}
}
}
}
}
```
---
## Cursor
Create or edit your Cursor MCP config file:
| Platform | Path |
| -------- | -------------------------------- |
| macOS | `~/.cursor/mcp.json` |
| Windows | `%USERPROFILE%\.cursor\mcp.json` |
```json
{
"mcpServers": {
"mewcp": {
"transport": "http",
"url": "https://gateway.mewcp.com/personal/mcp",
"headers": {
"Authorization": "Bearer MEWCP_KEY"
}
}
}
}
```
Restart Cursor. MewCP will be available in Agent mode.
---
## One entry, every app
Both configs above are complete. Every app you have connected is reachable through this single entry, and connecting another app in the dashboard needs no change here.
You will see four tools listed rather than the tools of each app: `search`, `get_schema`, `list_accounts`, and `call_tool`. Your editor's agent uses them to find and run the right tool for whatever you ask.
See [How MewCP works](/mewcp/getting-started#how-mewcp-works) for the detail.
---
## Try it
Open Copilot Chat or Cursor Agent and ask for something from an app you have connected:
```
Search my Notion for the Q3 planning doc and summarise it.
```
---
## Where to find your values
| Value | Where to get it |
| -------------- | --------------------- |
| `MEWCP_KEY` | Dashboard -> API Keys |
| Connected apps | Dashboard -> Servers |
---
## Document: TypeScript MCP Client
Connect to MewCP from a TypeScript or Node.js application.
URL: /mewcp/connect/typescript
# TypeScript MCP Client
## Install
```bash
npm install @modelcontextprotocol/sdk
```
---
## Connect
```typescript
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
const GATEWAY_URL = "https://gateway.mewcp.com/personal/mcp";
const MEWCP_KEY = "YOUR_MEWCP_KEY";
const transport = new StreamableHTTPClientTransport(new URL(GATEWAY_URL), {
requestInit: {
headers: {
Authorization: `Bearer ${MEWCP_KEY}`,
Accept: "application/json, text/event-stream",
},
},
});
const client = new Client({
name: "my-node-client",
version: "1.0.0",
});
await client.connect(transport);
const tools = await client.listTools();
console.log(
"Available tools:",
tools.tools.map((t) => t.name),
);
// -> ["search", "get_schema", "list_accounts", "call_tool"]
```
Every app you have connected is reachable through this one endpoint. You get four tools rather than the tools of each app, and you use them to reach the rest.
---
## Find a tool
```typescript
const found = await client.callTool({
name: "search",
arguments: { query: "calendar events" },
});
// each hit carries the server_maskedId and tool_name you need next
```
```typescript
const schema = await client.callTool({
name: "get_schema",
arguments: {
tools: [{ server_maskedId: "google-calendar", tool_name: "list_events" }],
},
});
```
---
## Run a tool
```typescript
const result = await client.callTool({
name: "call_tool",
arguments: {
server_maskedId: "google-calendar",
tool_name: "list_events",
args: {
calendar_id: "primary",
time_min: "2026-01-15T00:00:00Z",
time_max: "2026-01-16T00:00:00Z",
},
},
});
console.log(result);
```
If your code already knows which tool it wants, call `call_tool` directly. `search` and `get_schema` exist for agents that have to work it out at runtime.
---
## Choosing an account
When you have connected more than one account for the same app, list them and pass the one you want as `alias`:
```typescript
const accounts = await client.callTool({
name: "list_accounts",
arguments: { provider: "google-gmail" },
});
const result = await client.callTool({
name: "call_tool",
arguments: {
server_maskedId: "google-gmail",
tool_name: "list_messages",
args: { max_results: 10 },
alias: "work",
},
});
```
With a single connected account you can leave `alias` out.
---
## B2B: audience member credential routing
If you are managing audience member credentials via the [MewCP Auth API](/mewcp-auth), identify the end user with a header and MewCP resolves their stored credential automatically:
```typescript
const transport = new StreamableHTTPClientTransport(new URL(GATEWAY_URL), {
requestInit: {
headers: {
Authorization: `Bearer ${MEWCP_KEY}`,
"x-mewcp-enduser-id": currentUser.id,
},
},
});
```
---
## Where to find your values
| Value | Where to get it |
| ------------------ | --------------------- |
| `YOUR_MEWCP_KEY` | Dashboard -> API Keys |
| Connected apps | Dashboard -> Servers |
---
## Document: Python MCP Client
Connect to MewCP from a Python application using fastmcp.
URL: /mewcp/connect/python
# Python MCP Client
## Install
```bash
pip install fastmcp
```
---
## Connect
```python
import asyncio
from fastmcp import Client
GATEWAY_URL = "https://gateway.mewcp.com/personal/mcp"
MEWCP_KEY = "YOUR_MEWCP_KEY"
headers = {"Authorization": f"Bearer {MEWCP_KEY}"}
async def main():
client = Client(GATEWAY_URL, headers=headers)
async with client:
await client.ping()
tools = await client.list_tools()
print("Available tools:", [t.name for t in tools])
# -> ["search", "get_schema", "list_accounts", "call_tool"]
asyncio.run(main())
```
Every app you have connected is reachable through this one endpoint. You get four tools rather than the tools of each app, and you use them to reach the rest.
---
## Find a tool
```python
found = await client.call_tool("search", {"query": "calendar events"})
# each hit carries the server_maskedId and tool_name you need next
schema = await client.call_tool(
"get_schema",
{"tools": [{"server_maskedId": "google-calendar", "tool_name": "list_events"}]},
)
```
---
## Run a tool
```python
result = await client.call_tool(
"call_tool",
{
"server_maskedId": "google-calendar",
"tool_name": "list_events",
"args": {
"calendar_id": "primary",
"time_min": "2026-01-15T00:00:00Z",
"time_max": "2026-01-16T00:00:00Z",
},
},
)
print(result)
```
If your code already knows which tool it wants, call `call_tool` directly. `search` and `get_schema` exist for agents that have to work it out at runtime.
---
## Choosing an account
When you have connected more than one account for the same app, list them and pass the one you want as `alias`:
```python
accounts = await client.call_tool("list_accounts", {"provider": "google-gmail"})
result = await client.call_tool(
"call_tool",
{
"server_maskedId": "google-gmail",
"tool_name": "list_messages",
"args": {"max_results": 10},
"alias": "work",
},
)
```
With a single connected account you can leave `alias` out.
---
## B2B: audience member credential routing
If you are managing audience member credentials via the [MewCP Auth API](/mewcp-auth), identify the end user with a header and MewCP resolves their stored credential automatically:
```python
headers = {
"Authorization": f"Bearer {MEWCP_KEY}",
"x-mewcp-enduser-id": current_user.id,
}
```
---
## Where to find your values
| Value | Where to get it |
| ---------------- | --------------------- |
| `YOUR_MEWCP_KEY` | Dashboard -> API Keys |
| Connected apps | Dashboard -> Servers |
---
## Document: OpenAI Codex
Connect MewCP to the OpenAI Codex CLI.
URL: /mewcp/connect/codex
# OpenAI Codex
## Prerequisites
- Codex CLI installed: `npm install -g @openai/codex`
- A MewCP Key, see [Authentication](/mewcp/authentication)
- At least one app connected in the dashboard under **Servers**
---
## Configuration
Add MewCP to `~/.codex/config.yaml`:
```yaml
mcpServers:
mewcp:
type: http
url: https://gateway.mewcp.com/personal/mcp
headers:
Authorization: "Bearer MEWCP_KEY"
```
MewCP will be available on the next `codex` invocation.
This is the entire configuration. Every app you have connected is reachable through this one entry, and connecting another app in the dashboard needs no change here.
---
## What you will see
Codex will list four tools rather than the tools of each app: `search`, `get_schema`, `list_accounts`, and `call_tool`. It uses them to find and run the right tool for whatever you ask.
See [How MewCP works](/mewcp/getting-started#how-mewcp-works) for the detail.
---
## Try it
Ask for something from an app you have connected:
```bash
codex "Check my calendar for tomorrow and summarise the day"
```
---
## Where to find your values
| Value | Where to get it |
| -------------- | --------------------- |
| `MEWCP_KEY` | Dashboard -> API Keys |
| Connected apps | Dashboard -> Servers |
---
## Document: Claude Desktop
Connect MewCP to Claude Desktop.
URL: /mewcp/connect/claude-desktop
# Claude Desktop
## Prerequisites
- Claude Desktop installed ([download](https://claude.ai/download))
- Node.js installed (used by the `mcp-remote` bridge)
- A MewCP Key, see [Authentication](/mewcp/authentication)
- At least one app connected in the dashboard under **Servers**
---
## Configuration
Open your Claude Desktop config file:
| Platform | Path |
| -------- | ----------------------------------------------------------------- |
| macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |
| Windows | `%APPDATA%\Claude\claude_desktop_config.json` |
Add MewCP under `mcpServers`:
```json
{
"mcpServers": {
"mewcp": {
"command": "npx",
"args": [
"-y",
"mcp-remote@latest",
"https://gateway.mewcp.com/personal/mcp",
"--header",
"Authorization: Bearer ${MEWCP_KEY}"
],
"env": {
"MEWCP_KEY": "your_key_here"
}
}
}
}
```
Save the file and restart Claude Desktop. A tools icon will appear in the chat panel when MewCP is connected.
This is the entire configuration. Every app you have connected is reachable through this one entry, and connecting another app in the dashboard needs no change here.
---
## What you will see
Claude will list four tools rather than the tools of each app: `search`, `get_schema`, `list_accounts`, and `call_tool`. That is expected. Claude uses them to find and run the right tool for whatever you ask, so you keep asking in plain language.
See [How MewCP works](/mewcp/getting-started#how-mewcp-works) for the detail.
---
## Try it
Ask for something from an app you have connected:
```
What is on my calendar tomorrow?
```
Claude will find the calendar tool, run it against your connected account, and answer.
If you have two accounts connected for the same app, say which one you mean and Claude will pick it by alias:
```
Check my work Gmail for anything from the design team.
```
---
## Where to find your values
| Value | Where to get it |
| --------------- | ---------------------------- |
| `your_key_here` | Dashboard -> API Keys |
| Connected apps | Dashboard -> Servers |
---
## Document: MewCP Key
The key used to authenticate MCP client connections to the gateway.
URL: /mewcp/authentication/mewcp-key
# MewCP Key
A **MewCP Key** authenticates MCP client connections to the gateway. Every time Claude Desktop, VS Code, or your application makes a request through `gateway.mewcp.com`, it presents this key.
One key covers every app you have connected. You do not need a separate key per app, and you do not need to change the key when you connect a new one.
---
## Format
```
mcp_live_
```
Example: `mcp_live_7df44e73e8cd42bbf4860ffc66520ef...`
---
## How to get one
1. Log in to the [MewCP dashboard](https://mewcp.com/dashboard)
1. Go to **API Keys**
1. Copy your **MewCP Key**
---
## How to use it
Pass it as a Bearer token in the `Authorization` header:
```
Authorization: Bearer MEWCP_KEY
```
In client configs:
```json
"headers": {
"Authorization": "Bearer MEWCP_KEY"
}
```
Clients that cannot set an `Authorization` header can send the key as `x-mewcp-key` instead.
The key goes with your toolset endpoint:
```
https://gateway.mewcp.com/personal/mcp
```
---
## What it does and does not carry
The MewCP Key identifies **you**. It does not carry any app credential.
When a tool runs, MewCP looks up the account you connected for that app and injects it into the upstream request at that moment. Your connected app credentials never travel to your client, your agent, or the model. The only secret in your config is this key.
---
## Best practices
- **Never put it in frontend code.** MewCP Keys are for server-to-gateway connections only.
- **Use an environment variable.** Keep the key out of committed config files.
- **Revoke if compromised.** Go to **API Keys** and click **Revoke**. The old key stops working immediately.
---
## Document: Account API Keys
Keys for programmatic access to MewCP management APIs from your backend.
URL: /mewcp/authentication/account-api-keys
# Account API Keys
An **Account API Key** authenticates programmatic calls to MewCP's management APIs. Your backend uses this key to start OAuth flows for audience, get hosted credential form URLs, and manage audience member credential state via the [MewCP Auth API](/mewcp-auth).
---
## Format
```
mewcp_acct_
```
Example: `mewcp_acct_7df44e73e8cd42bbf4860ffc66520efb62d973615dc2c0f7fb5607fb82d75b53`
---
## How to get one
1. Go to **Dashboard -> Developer -> Account API Keys**
1. Click **Generate Key**, give it a label, and copy the key
---
## How to use it
Pass it as a Bearer token in the `Authorization` header. Every MewCP Auth API endpoint also requires an `x-mewcp-key` header: the MewCP Key of the specific business-mode server you're acting on (see [MewCP Key](/mewcp/authentication/mewcp-key)). The two are not interchangeable and both are required:
```bash
curl https://gateway.mewcp.com/end-users \
-H "Authorization: Bearer mewcp_acct_YOUR_KEY" \
-H "x-mewcp-key: mcp_live_YOUR_SERVER_KEY"
```
TypeScript:
```typescript
const res = await fetch("https://gateway.mewcp.com/end-users", {
headers: {
Authorization: `Bearer ${process.env.MEWCP_ACCOUNT_KEY}`,
"x-mewcp-key": process.env.MEWCP_SERVER_KEY,
},
});
```
Python:
```python
import httpx
resp = httpx.get(
"https://gateway.mewcp.com/end-users",
headers={
"Authorization": f"Bearer {MEWCP_ACCOUNT_KEY}",
"x-mewcp-key": MEWCP_SERVER_KEY,
},
)
```
---
## What you can do with it
| Action | Endpoint |
| ------------------------------------ | --------------------------------------------------- |
| Start OAuth flow for a user | `POST /oauth/{provider}/start` |
| Get hosted static credential form | `POST /credentials/static/{providerSlug}/connect` |
| List audience for a server | `GET /end-users` |
| Get an audience member's credentials | `GET /end-users/{externalUserId}` |
| Revoke a user's credential | `DELETE /end-users/{externalUserId}` |
Every action above is scoped to the single server identified by `x-mewcp-key`. There's no call that lists or manages audience across every server at once.
Full reference in the [MewCP Auth API](/mewcp-auth) docs.
---
## Best practices
- **Keep it server-side only.** Never expose Account API Keys in frontend code or mobile apps.
- **One key per environment.** Use separate keys for production, staging, and local development.
- **Revoke if compromised.** Go to **Developer -> Account API Keys** and click **Revoke**.
---
## Document: Static Credentials Integration Guide
How to integrate MewCP's hosted credential form so your users can connect API-key-based providers like Gemini, Razorpay, and Firecrawl.
URL: /mewcp/auth-api/static-credentials
# Static Credentials Integration Guide
Some MCP server providers - like **Gemini, Razorpay, Firecrawl, OpenAI**, and others - don't use OAuth. They issue API keys or secrets that users paste in manually. MewCP handles this with a **hosted form**: you generate a secure link, your user opens it, fills in their credentials, and MewCP encrypts and stores them. You never see or handle the raw keys.
---
## What MewCP does for you
- Generates a short-lived, signed form URL for each user
- Hosts the credential input form - no frontend work required from you
- Encrypts all sensitive fields (API keys, secrets) before storage in MewCP's vault
- Ties every credential to an `externalUserId` you supply
- Handles success and failure feedback - either redirecting to your app or showing a confirmation page
---
## Before you start
1. **Add the MCP server to your subscription**: the provider (e.g. `gemini`, `razorpay`) must be an active server in your MewCP subscription. If it isn't, the API returns `403`. Add it from **Dashboard → Servers → Add Server**.
2. **Get the server's MewCP Key**: go to **Dashboard (mode=business) → Servers → select server → select key → Copy Key**. You'll send this on every `POST /credentials/static/{providerSlug}/connect` call, alongside your Account API Key, see below.
---
## Integration flow
1. **Generate a hosted form URL**
Call `POST /credentials/static/{providerSlug}/connect` from your backend. Two headers are required: your Account API Key (`Authorization`) and the MewCP Key of the specific server you're connecting this user to (`x-mewcp-key`). Pass the user's ID and, if you have a frontend, a callback URL. You can also pass optional user metadata, which MewCP stores alongside the credential for display in your dashboard:
```http
POST /credentials/static/gemini/connect
Authorization: Bearer MEWCP_ACCT_API_KEY
x-mewcp-key: MEWCP_KEY
{
"externalUserId": "user_123",
"frontendCallbackUrl": "https://yourapp.com/credentials/callback",
"externalUserMeta": {
"name": "Jane Smith",
"email": "jane@example.com",
"username": "janesmith"
}
}
```
| Field | Required | Description |
| --------------------------- | -------- | ----------------------------------------------------- |
| `externalUserId` | Yes | Your internal user identifier |
| `frontendCallbackUrl` | No | Where MewCP redirects the user after form submission |
| `externalUserMeta.name` | No | User's display name, stored for your reference |
| `externalUserMeta.email` | No | User's email, stored for your reference |
| `externalUserMeta.username` | No | User's username, stored for your reference |
If `x-mewcp-key` is missing, invalid, not a business-mode server key, or belongs to a different provider than `{providerSlug}` in the path, the call fails with `401`/`400` before any form URL is generated.
You get back:
```json
{
"hostedFormUrl": "https://gateway.mewcp.com/connect/static?token=...",
"expiresInMinutes": 5
}
```
The URL is valid for **5 minutes**. Generate it close to when the user will open it.
1. **Send the URL to your user**
**If you have a frontend (web app):**
Redirect the user to the `hostedFormUrl`, or open it as a new tab:
```js
// Redirect the current page
window.location.href = hostedFormUrl;
// Or open as a new tab
window.open(hostedFormUrl, "_blank");
```
After the user submits their credentials, MewCP redirects to your `frontendCallbackUrl`:
| Result | Query params on your callback URL |
| ------- | --------------------------------------- |
| Success | `?provider=gemini&success=true` |
| Error | MewCP shows an error page with details |
Handle the result on your callback page:
```js
// On your frontendCallbackUrl page
const params = new URLSearchParams(window.location.search);
if (params.get("success") === "true") {
// show success, redirect to dashboard, etc.
}
```
**If you have no frontend (local tools / server-only setups):**
Open the `hostedFormUrl` in a browser, fill in the API key, and submit. MewCP will show a **"Connected"** confirmation page. The credential is saved, no further action needed.
**Other delivery methods:**
- Email the link to the user
- Show it as a button in your app's settings page
- Send it via an in-app notification
Just ensure the user opens it within 5 minutes of generation.
1. **Use the connection** 🚀
Once connected, route your user's MCP requests through the gateway with their `externalUserId` in the header:
```http
x-external-user-id: user_123
```
MewCP resolves the stored credential and injects it into the provider call.
---
## Security
- All sensitive fields (API keys, secrets) are **encrypted at rest** in MewCP's vault
- The form URL contains a short-lived signed token - it cannot be reused or tampered with
- Your backend never handles raw credentials - only the `externalUserId` reference
- You can revoke a user's credential at any time via the [Audience API](/mewcp-auth#tag/Audience)
---
## Document: OAuth Integration Guide
How to integrate MewCP's OAuth flow so your users can connect providers like Google, Slack, and GitHub to your application.
URL: /mewcp/auth-api/oauth-integration
# OAuth Integration Guide
MCP servers for providers like **Google, Slack, GitHub, Notion**, and others use OAuth - the same login flow your users already know ("Sign in with Google"). MewCP handles the entire OAuth lifecycle for you: token exchange, encrypted storage, and automatic refresh. You never touch a raw access token.
---
## What MewCP does for you
- Runs the OAuth handshake with the provider on your behalf
- Encrypts and stores the access token and refresh token in MewCP's vault
- Automatically refreshes tokens before they expire - no token management on your side
- Ties every credential to an `externalUserId` you supply, so you can identify which of your users connected which account
---
## Before you start
1. **Add the MCP server to your subscription** - the provider (e.g. `google`, `github`) must be an active server in your MewCP subscription. If it isn't, the API returns `403`. Do this from **Dashboard → Add Server**.
2. **Register your OAuth app and assign it to a business-mode server key**: go to **Dashboard (mode=business) → Servers → select server → Register OAuth Client**, add your `client_id` and `client_secret` from the provider (e.g. Google Cloud Console, Slack API, GitHub OAuth Apps), and set the redirect URI to `https://gateway.mewcp.com/oauth/callback`.
3. **Get the server's MewCP Key**: go to **Dashboard (mode=business) → Servers → select server → select key → Copy Key**. You'll send this on every `POST /oauth/{provider}/start` call, alongside your Account API Key, see below.
---
## Integration flow
1. **Start the OAuth flow**
Call `POST /oauth/{provider}/start` from your backend. Two headers are required: your Account API Key (`Authorization`) and the MewCP Key of the specific server you're connecting this user to (`x-mewcp-key`). The OAuth app used is always the one assigned to that server key, so there's no app selection in the request body. Pass the user's ID and, if you have a frontend, a callback URL. You can also pass optional user metadata, which MewCP stores alongside the credential for display in your dashboard:
```http
POST /oauth/google/start
Authorization: Bearer MEWCP_ACCT_API_KEY
x-mewcp-key: MEWCP_KEY
{
"externalUserId": "user_123",
"frontendCallbackUrl": "https://yourapp.com/oauth/callback",
"externalUserMeta": {
"name": "Jane Smith",
"email": "jane@example.com",
"username": "janesmith"
}
}
```
| Field | Required | Description |
| --------------------------- | -------- | ----------------------------------------------------- |
| `externalUserId` | Yes | Your internal user identifier |
| `frontendCallbackUrl` | No | Where MewCP redirects the user after OAuth completes |
| `externalUserMeta.name` | No | User's display name, stored for your reference |
| `externalUserMeta.email` | No | User's email, stored for your reference |
| `externalUserMeta.username` | No | User's username, stored for your reference |
If `x-mewcp-key` is missing, invalid, not a business-mode server key, or belongs to a different provider than `{provider}` in the path, the call fails with `401`/`400` before any OAuth URL is generated.
You get back:
```json
{
"authUrl": "https://accounts.google.com/o/oauth2/auth?client_id=...",
"state": "a3f9..."
}
```
The `state` value is internal: MewCP uses it to verify the callback. You do not need to store or validate it.
1. **Open the auth URL for your user**
**If you have a frontend (web app):**
Open the URL as a popup, the standard OAuth pattern. The popup must be opened from a user action (e.g. a button click), otherwise browsers will block it.
```js
// Open the popup on button click
const popup = window.open(authUrl, "mewcp-oauth", "width=500,height=650");
// Listen for the result message from your callback page
window.addEventListener("message", (event) => {
if (event.origin !== window.location.origin) return;
const { provider, success, error } = event.data;
if (success) {
// OAuth completed - update your UI
console.log(`${provider} connected`);
} else if (error) {
console.error("OAuth failed:", error);
}
});
```
After the user logs in, MewCP redirects the popup to your `frontendCallbackUrl`:
| Result | Query params on your callback URL |
| ------- | ---------------------------------- |
| Success | `?provider=google&success=true` |
| Error | `?oauth_error=` |
Your callback page needs to forward this result to the parent window and close the popup:
```js
// On your frontendCallbackUrl page
const params = new URLSearchParams(window.location.search);
window.opener?.postMessage(
{
provider: params.get("provider"),
success: params.get("success") === "true",
error: params.get("oauth_error") ?? null,
},
window.location.origin,
);
window.close();
```
**If you prefer a full redirect (no popup):**
Instead of opening a popup, redirect the user directly to the `authUrl`. After OAuth completes, MewCP redirects them back to your `frontendCallbackUrl`. Handle the result there as a normal page load:
```js
window.location.href = authUrl;
```
```js
// On your frontendCallbackUrl page
const params = new URLSearchParams(window.location.search);
if (params.get("success") === "true") {
// show success, redirect to dashboard, etc.
}
```
**If you have no frontend (local tools / server-only setups):**
Simply open the `authUrl` in a browser, log in, and you're done. MewCP will show a **"Connected"** confirmation page with a close button. The credential is saved automatically, no further action needed.
1. **Use the connection** 🚀
Once connected, route your user's MCP requests through the gateway with their `externalUserId` in the header:
```http
x-external-user-id: user_123
```
MewCP resolves the stored credential and makes the authenticated call on their behalf.
---
## Security
- Access tokens and refresh tokens are **encrypted at rest** in MewCP's vault
- Your backend never need to handles raw credentials - only an opaque `externalUserId` reference
- Token refresh happens server-side, automatically, before expiry
- You can revoke a user's credential at any time via the [Audience API](/mewcp-auth#tag/Audience)