Quickstart
Bring up the Cortex MCP server locally, mint a bearer token, and call a tool from the client of your choice. Five minutes, two commands, no SaaS dependency.
1. Bring up the dev infrastructure
From the repo root, start Postgres, Redis, and LocalStack alongside the Next.js web app. The MCP server itself runs as a separate process — we'll start it in step 3.
pnpm install
pnpm devpnpm dev launches Docker Compose services and the web app on http://localhost:3001.
2. Seed a bearer token in LocalStack Secrets Manager
The MCP server expects a JSON secret at the ARN in CONFIG_SECRET_ARN with a mcpBearerToken field. For local development against LocalStack:
export AWS_REGION=us-east-1
export LOCALSTACK_ENDPOINT=http://localhost:4566
aws --endpoint-url=$LOCALSTACK_ENDPOINT secretsmanager create-secret \
--name cortex/dev/config \
--secret-string '{"mcpBearerToken":"dev-mcp-token-CHANGE-ME"}'
# Save the returned ARN for the next step
export CONFIG_SECRET_ARN="arn:aws:secretsmanager:us-east-1:000000000000:secret:cortex/dev/config"3. Build & run the MCP server
pnpm --filter @cortex/mcp-server build
node packages/mcp-server/dist/index.jsThe server listens on http://localhost:3002/mcp. A health probe is at /health (unauthenticated). Logs are JSON; requestId ties together every message in a session.
4. Connect a client
Claude Desktop
Open the config file at ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\\Claude\\claude_desktop_config.json (Windows) and add a server entry:
{
"mcpServers": {
"cortex": {
"url": "http://localhost:3002/mcp",
"headers": {
"Authorization": "Bearer dev-mcp-token-CHANGE-ME"
}
}
}
}Restart Claude Desktop. The Cortex tools should appear in the slash-command picker after the next message turn.
Cursor
In Cursor settings → MCP, click Add new MCP server and paste:
{
"cortex": {
"url": "http://localhost:3002/mcp",
"headers": {
"Authorization": "Bearer dev-mcp-token-CHANGE-ME"
}
}
}MCP Inspector (recommended for debugging)
The official inspector ships as an npx command. Point it at your local server with the bearer token in headers:
npx @modelcontextprotocol/inspector \
--transport streamable-http \
--server-url http://localhost:3002/mcp \
--header "Authorization: Bearer dev-mcp-token-CHANGE-ME"The inspector renders every tool with its schema, lets you call them one at a time, and shows the raw JSON-RPC payloads on both sides. Use this whenever a client misbehaves — it isolates server bugs from client bugs.
TypeScript — @modelcontextprotocol/sdk
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
const transport = new StreamableHTTPClientTransport(
new URL('http://localhost:3002/mcp'),
{
requestInit: {
headers: { Authorization: 'Bearer dev-mcp-token-CHANGE-ME' },
},
},
);
const client = new Client(
{ name: 'my-agent', version: '0.1.0' },
{ capabilities: {} },
);
await client.connect(transport);
const result = await client.callTool({
name: 'memory.recall',
arguments: { query: "what is sarah's role?", topK: 3 },
});
console.log(result);Python — mcp SDK
import asyncio
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
URL = "http://localhost:3002/mcp"
HEADERS = {"Authorization": "Bearer dev-mcp-token-CHANGE-ME"}
async def main() -> None:
async with streamablehttp_client(URL, headers=HEADERS) as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
result = await session.call_tool(
"memory.recall",
{"query": "what is sarah's role?", "topK": 3},
)
print(result)
asyncio.run(main())5. Verify with a real tool call
From any client above, call memory.recall with a query string. You should see ranked results from the seeded sandbox fixtures. If the call returns HTTP 401, double-check the bearer token matches the seed in step 2. If it returns HTTP 429, see Rate limits — the in-memory store doesn't reset on server restart in the current build.