The Commonplace
Home Papers Evidence Explore Trends Syntheses Digests References Docs 🎲 Workforce Futures

MCP server

Connect an AI assistant to the corpus over the Model Context Protocol. Configuration for every major client.

The Commonplace exposes its corpus over the Model Context Protocol, so an AI assistant can search papers, filter graded claims and pull a full paper record without you leaving the conversation. Access is read-only. Nothing an assistant does through this endpoint can change the corpus.

The endpoint

URL
https://commonplace.workforcefutures.net/mcp
Transport
Streamable HTTP. POST only; responses are application/json.
Authentication
Authorization: Bearer YOUR_API_KEY
Protocol revisions
2024-11-05, 2025-03-26, 2025-06-18, 2025-11-25. The server echoes back whichever of these your client asks for.
Tools
8 read-only tools. See the tool reference.

Getting a key. Keys are issued by hand. Contact Alex via workforcefutures.net and say roughly what you want to use it for. Treat the key as a personal credential: it identifies you to the rate limiter, so a key you share is a budget you share.

Check it works before wiring up a client

Every client failure looks the same from inside an editor, so it is worth one curl first. This asks the server what tools it has:

curl -sS https://commonplace.workforcefutures.net/mcp \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

A working key returns a JSON object with a result.tools array. A bad or missing key returns 401 with {"error":"unauthorized"}. If that works and your editor still does not connect, the problem is the client configuration, not the server or the key.

Client configuration

Configuration below is grouped by what the client actually supports. Anything that speaks Streamable HTTP natively should use the direct form. Clients that only launch local processes need the mcp-remote bridge.

Claude Code

Add it from the command line:

claude mcp add --transport http commonplace \
  https://commonplace.workforcefutures.net/mcp \
  --header "Authorization: Bearer YOUR_API_KEY"

Or commit a .mcp.json at the project root so the whole team picks it up:

{
  "mcpServers": {
    "commonplace": {
      "type": "http",
      "url": "https://commonplace.workforcefutures.net/mcp",
      "headers": { "Authorization": "Bearer YOUR_API_KEY" }
    }
  }
}

The type field matters. An entry with a url but no type is read as a local stdio server and will fail to start.

VS Code and GitHub Copilot

In .vscode/mcp.json for one workspace:

{
  "servers": {
    "commonplace": {
      "type": "http",
      "url": "https://commonplace.workforcefutures.net/mcp",
      "headers": { "Authorization": "Bearer YOUR_API_KEY" }
    }
  }
}

To keep the key out of the file, declare it as a prompted input. VS Code asks once and stores it for you:

{
  "inputs": [
    {
      "type": "promptString",
      "id": "commonplace-key",
      "description": "Commonplace API key",
      "password": true
    }
  ],
  "servers": {
    "commonplace": {
      "type": "http",
      "url": "https://commonplace.workforcefutures.net/mcp",
      "headers": { "Authorization": "Bearer ${input:commonplace-key}" }
    }
  }
}

Cursor

.cursor/mcp.json in a project, or ~/.cursor/mcp.json globally:

{
  "mcpServers": {
    "commonplace": {
      "url": "https://commonplace.workforcefutures.net/mcp",
      "headers": { "Authorization": "Bearer YOUR_API_KEY" }
    }
  }
}

Windsurf

In ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "commonplace": {
      "serverUrl": "https://commonplace.workforcefutures.net/mcp",
      "headers": { "Authorization": "Bearer YOUR_API_KEY" }
    }
  }
}

Zed

Under context_servers in settings.json:

{
  "context_servers": {
    "commonplace": {
      "url": "https://commonplace.workforcefutures.net/mcp",
      "headers": { "Authorization": "Bearer YOUR_API_KEY" }
    }
  }
}

Claude Desktop

Claude Desktop's config file describes local processes, so a remote server goes through the mcp-remote bridge. Edit claude_desktop_config.json (%APPDATA%\Claude\ on Windows, ~/Library/Application Support/Claude/ on macOS):

{
  "mcpServers": {
    "commonplace": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://commonplace.workforcefutures.net/mcp",
        "--header",
        "Authorization: Bearer YOUR_API_KEY"
      ]
    }
  }
}

Keep Authorization: Bearer YOUR_API_KEY as a single array element, exactly as shown. Splitting it across two elements, or dropping the space after the colon, produces a header the server will reject.

On npx. That configuration downloads and runs the mcp-remote package from npm every time the client starts, with whatever version is current. That is a real supply-chain dependency, not a detail. If that is not acceptable to you, install a pinned version yourself and point command at the installed binary, or use a client that speaks HTTP directly and skip the bridge.

OpenAI Agents SDK (Python)

import os
from agents import Agent, Runner
from agents.mcp import MCPServerStreamableHttp

async with MCPServerStreamableHttp(
    name="commonplace",
    params={
        "url": "https://commonplace.workforcefutures.net/mcp",
        "headers": {"Authorization": f"Bearer {os.environ['COMMONPLACE_API_KEY']}"},
    },
) as server:
    agent = Agent(
        name="Research assistant",
        instructions="Use the Commonplace tools for AI-economics evidence.",
        mcp_servers=[server],
    )
    result = await Runner.run(agent, "What does the evidence say about AI and wages?")
    print(result.final_output)

OpenAI Responses API

import os
from openai import OpenAI

client = OpenAI()
response = client.responses.create(
    model="gpt-4o",
    tools=[{
        "type": "mcp",
        "server_label": "commonplace",
        "server_url": "https://commonplace.workforcefutures.net/mcp",
        "headers": {"Authorization": f"Bearer {os.environ['COMMONPLACE_API_KEY']}"},
        "require_approval": "never",
    }],
    input="Summarise the strongest evidence on AI and developer productivity.",
)
print(response.output_text)

MCP Python SDK

import asyncio, os, httpx2
from mcp import Client
from mcp.client.streamable_http import streamable_http_client

async def main():
    async with httpx2.AsyncClient(
        headers={"Authorization": f"Bearer {os.environ['COMMONPLACE_API_KEY']}"},
        timeout=httpx2.Timeout(30.0, read=120.0),
    ) as http_client:
        transport = streamable_http_client(
            "https://commonplace.workforcefutures.net/mcp",
            http_client=http_client,
        )
        async with Client(transport) as client:
            tools = await client.list_tools()
            print([t.name for t in tools.tools])
            result = await client.call_tool("search_papers", {"query": "wages", "limit": 5})
            print(result.content[0].text)

asyncio.run(main())

Headers go on the httpx2 client, not on streamable_http_client, which does not take a headers argument.

MCP Inspector

Useful for confirming a key works and for reading the raw tool schemas:

npx @modelcontextprotocol/inspector --cli \
  https://commonplace.workforcefutures.net/mcp \
  --transport http \
  --header "Authorization: Bearer YOUR_API_KEY" \
  --method tools/list

If the key is wrong, Inspector does not simply report the 401. It tries to start an interactive OAuth flow and fails with a message about needing a TTY. That means the key was rejected, not that OAuth is required.

Rate limits

The endpoint is metered per key, in three tiers, because one of the tools costs real money on every call:

ClassWhat it coversBudget
Control initialize, ping, tools/list, notifications 240/minute
Tools Ordinary tool calls that only read the local corpus 60/minute
Billable semantic_search, which computes an embedding per call 10/minute, and a daily cap

Over budget returns HTTP 429 with a Retry-After header. Normal interactive use does not come close to these numbers; a runaway loop does. If you have a legitimate bulk use case, ask rather than working around it.

When it does not connect

401 unauthorized
The key is missing, wrong, or the header is malformed. The value must be Bearer, one space, then the key. Confirm with the curl above.
405 method not allowed
Something sent GET. This server is POST-only and has no server-initiated event stream. A client that requires a GET/SSE channel cannot use it directly; bridge it with mcp-remote.
429 rate limited
You are over one of the budgets above. Wait for Retry-After. If this happens during ordinary use, tell us, because the budget is wrong.
400 unsupported protocol version
Your client sent an MCP-Protocol-Version the server does not implement. The supported list is in the error body.
The client starts but shows no tools
Usually a config entry missing its type, so the client is trying to run it as a local command. Check the client's MCP log.

Vendor configuration formats change. If a snippet here does not match what your client expects, trust the client's own documentation and tell us so this page can be corrected.