MCP Server

Connect Claude, Cursor, and your own agents to your document corpus

The Pyramid AI MCP server exposes your organization’s document corpus over the Model Context Protocol — an open standard for connecting AI assistants to external tools and data. Any MCP-aware client (Claude, Cursor, or a custom agent built on the MCP SDK) can search your documents and get back grounded answers with source links, without you writing a line of integration code.

Search documents

Run hybrid semantic + keyword search and get back ranked documents with their source URLs.

Answer questions

Get a finished, cited answer synthesized from the most relevant passages in your corpus.

Stay grounded

Every result carries a source link, so your agent can always cite where an answer came from.

MCP access is gated per organization. If your key returns 403 FEATURE_NOT_ENABLED, ask your Pyramid AI account manager to enable the MCP server for your org.

Endpoint

POST https://api.pyramid-ai.com/api/v2/mcp
EnvironmentBase URLKey prefix
Productionhttps://api.pyramid-ai.com/api/v2/mcppai_live_*
Staginghttps://api-staging.pyramid-ai.com/api/v2/mcppai_test_*
  • Transport: Streamable HTTP, stateless — one POST per JSON-RPC exchange, no session to manage.
  • Only POST is served; GET and DELETE return a JSON-RPC 405.

Connect in under 5 minutes

1

Get an API key

Create a key in the Pyramid AI platform, or use one you already have. Production keys (pai_live_*) work against api.pyramid-ai.com; staging keys (pai_test_*) against api-staging.pyramid-ai.com. See Authentication for key formats, environments, and rotation.

Store your API key securely — it is shown only once at creation time and cannot be retrieved later.

2

Add the server to your client

Point your MCP client at the endpoint and pass your key as a bearer token. See Connect your client below for the exact config for Claude, Cursor, and the SDK.

3

Ask a question

Once connected, your agent can call the search_documents and answer_question tools directly. Try: “Search the corpus for bamboo scaffolding safety requirements.”

Authentication

The MCP endpoint uses the same bearer API-key auth as every other Pyramid AI API route — no OAuth flow. Send your key in the Authorization header, and because the transport is Streamable HTTP, your client must advertise both content types in Accept:

Authorization: Bearer pai_live_YOUR_KEY_HERE
Content-Type: application/json
Accept: application/json, text/event-stream

Responses come back as a one-shot SSE frame (event: message / data: <json-rpc>). Most MCP clients and SDKs handle this framing for you.

Connect your client

Claude Code

$claude mcp add pyramid-corpus --transport http \
> https://api.pyramid-ai.com/api/v2/mcp \
> --header "Authorization: Bearer pai_live_YOUR_KEY_HERE"

Claude Desktop / Cursor

Add the server to your mcpServers config (claude_desktop_config.json for Claude Desktop, .cursor/mcp.json for Cursor):

1{
2 "mcpServers": {
3 "pyramid-document-corpus": {
4 "type": "http",
5 "url": "https://api.pyramid-ai.com/api/v2/mcp",
6 "headers": { "Authorization": "Bearer pai_live_YOUR_KEY_HERE" }
7 }
8 }
9}

Custom agent (TypeScript SDK)

1import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
3
4const transport = new StreamableHTTPClientTransport(
5 new URL('https://api.pyramid-ai.com/api/v2/mcp'),
6 { requestInit: { headers: { Authorization: 'Bearer pai_live_YOUR_KEY_HERE' } } },
7);
8
9const client = new Client({ name: 'my-agent', version: '1.0' });
10await client.connect(transport);
11
12const result = await client.callTool({
13 name: 'answer_question',
14 arguments: { query: 'What are the requirements for road opening works?' },
15});

MCP Inspector (visual debugging)

$npx @modelcontextprotocol/inspector

Choose transport Streamable HTTP, set the URL to the endpoint, and add the Authorization: Bearer … header.

Tools

The server exposes two tools. Both accept the same arguments — the difference is whether you want raw hits to reason over yourself, or a finished, cited answer.

You wantCallTypical latency
Ranked documents your own model reasons oversearch_documents~5s
A finished answer with [n] citationsanswer_question~20–25s

Shared arguments

ArgumentTypeRequiredNotes
querystringyesNatural-language question or keywords.
scopeenumnoOne of technical_circulars, general_circulars, standards_and_codes, practice_notes, safety_health, publications, press_releases, everything. Omit it to search all technical documents and auto-exclude noise — the right default for almost every query. See Scope & broadening.
startDatestring (ISO)noInclusive lower bound, e.g. 2024-01-01T00:00:00Z. Only set for an explicit time window — date filters drop undated documents, which are common in this corpus.
endDatestring (ISO)noInclusive upper bound; set only alongside startDate.

search_documents

Hybrid (semantic vector + full-text BM25) search over the corpus, returning ranked documents with their source links. The tool result is a JSON payload:

1{
2 "query": "bamboo scaffolding",
3 "scope": "technical_circulars",
4 "requestedScope": "technical_circulars",
5 "broadened": true,
6 "hasResults": true,
7 "count": 1,
8 "results": [
9 {
10 "title": "DEVB TC(W) No. 1/2025",
11 "url": "https://www.devb.gov.hk/tcw-1-2025.pdf",
12 "snippet": "Guidance on bamboo scaffolding...",
13 "score": 0.91
14 }
15 ]
16}

Always surface results[].url to the user — it is the canonical source link. When hasResults is false, tell the user nothing relevant was found and ask them to refine; do not answer from prior knowledge.

answer_question

Runs the same hybrid search, then synthesizes a complete written answer from the top passages, with bracketed [n] citation markers. The answer is atomic — it arrives whole after ~20–25s (MCP tool results cannot stream).

1{
2 "query": "what are the requirements for road opening works?",
3 "answer": "Road opening works must follow the permit conditions [1]...",
4 "hasResults": true,
5 "scope": "default",
6 "requestedScope": "default",
7 "broadened": false,
8 "citations": [
9 { "ref": 1, "title": "HyD TC No. 5/2024", "url": "https://..." }
10 ],
11 "sources": [
12 { "ref": 1, "title": "HyD TC No. 5/2024", "url": "https://...", "snippet": "...", "score": 0.88 }
13 ]
14}
  • citations is the subset of sources the answer actually references via its [n] markers.
  • sources lists every passage the search retrieved, whether or not it was cited.
  • The payload is also returned as structuredContent for SDK clients that prefer structured parsing.

Scope & broadening

A narrow scope is a relevance hint, not a hard filter. When you pass a narrow technical scope, the search runs over the broad technical pool so a wrong category guess can’t hide the right document — and the response sets broadened: true with your original choice preserved in requestedScope. Results may therefore include other document types.

  • answer_question will prefer the requested document type and add a caveat in the answer when it relies on another.
  • press_releases and everything are exact — they are never broadened.

A hasResults: false response means nothing ranked as relevant; it does not prove the document doesn’t exist. Refine the query rather than concluding the corpus lacks coverage.

Progress updates

MCP tool results don’t stream, but answer_question emits coarse notifications/progress while it works — if your call opts in with a progressToken in the request _meta:

1"params": {
2 "name": "answer_question",
3 "arguments": { "query": "..." },
4 "_meta": { "progressToken": "t1" }
5}

Stages: Searching the document corpus… (10/100) → Retrieved N documents — generating answer… (40/100) → Answer ready. (100/100). SDK clients receive these via the onprogress callback on callTool. Budget a 60-second client-side timeout for answer_question.

Raw JSON-RPC (curl)

For testing or non-SDK clients, call the JSON-RPC API directly. The Accept header must advertise both content types:

$curl -sS https://api.pyramid-ai.com/api/v2/mcp \
> -H "Authorization: Bearer pai_live_YOUR_KEY_HERE" \
> -H "Content-Type: application/json" \
> -H "Accept: application/json, text/event-stream" \
> -d '{
> "jsonrpc": "2.0",
> "id": 1,
> "method": "tools/call",
> "params": {
> "name": "search_documents",
> "arguments": { "query": "bamboo scaffolding safety requirements" }
> }
> }'

List the available tools with "method": "tools/list".

Troubleshooting

SymptomCause & fix
401 UNAUTHORIZEDMissing/invalid bearer key, or a pai_test_* key against production (and vice versa). Check the key matches the environment.
403 FEATURE_NOT_ENABLEDYour org doesn’t have MCP enabled. Contact your account manager.
406 / transport errorThe Accept header is missing text/event-stream. Add application/json, text/event-stream.
answer_question times outClient timeout is below ~30s. Raise it — generation takes ~20–25s.
Empty results with a scope setSet scope: "everything" to include all document types, or drop the date filters.

Next steps