Skip to main content

Connect an AI assistant over MCP

This guide creates an API key for an AI assistant, checks the Model Context Protocol (MCP) connection with curl, configures an MCP client and runs a first search through the assistant. Integrators follow this guide to give an AI assistant access to a pipeline, and administrators follow this guide to issue the assistant's key. The examples use the support-kb pipeline from First search and the shell variables from Authenticate. MCP server describes the MCP server, and MCP tools lists the tools.

MCP URL​

The MCP URL is the base URL of the API server followed by /mcp, without a trailing slash. The assistant's computer reaches the API server through one of the access paths of API and dashboard access:

Access pathMCP URL
Ingress or HTTPRoutehttps://<host name>/mcp
Port forward on the assistant's computerhttp://localhost:8080/mcp
Inside the clusterhttp://foundation4ai-api-server.foundation4ai.svc.cluster.local/mcp

The MCP server accepts any host name unless the deployment restricts the host names with mcp.allowed_hosts, as described in Host names. A deployment with more than one API server replica needs session affinity at the ingress for MCP clients, because a session exists only on the replica that created the session.

Assistant key​

An AI assistant receives its own API key, so that the key's permissions and classification allow-list limit what the assistant can reach, and so that the key can be revoked without affecting other client applications. The language model of the assistant chooses the arguments of each tool call, including the classifications of a search. The allow-list therefore holds only the classifications that every user of the assistant may read.

This guide creates a key that searches and reads support-kb with the classification internal, which inherits public. The key holds no permission on the pipeline's text splitter and no write permission, so the assistant cannot add, expire or delete documents. API keys for AI assistants lists the permissions for the other tools.

The requests in this section run with an administration key, as described in Manage API keys and permissions. Create the key:

curl -X POST "$FOUNDATION4_URL/api-keys" \
-H "x-api-key: $FOUNDATION4_API_KEY" \
-H "x-api-key-secret: $FOUNDATION4_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"name": "support-assistant",
"description": "AI assistant for the support knowledge base",
"expiration": "2027-09-30T00:00:00Z"
}'

Expected result: status 201 and the new key, with the generated secret in secret. Foundation4 returns the secret only in this response. Set the variables for the remaining steps:

export ASSISTANT_KEY_ID=<id from the response>
export ASSISTANT_KEY_SECRET=<secret from the response>

Grant read and execute permission (5) on the pipeline, with the allow-list internal:

curl -X POST "$FOUNDATION4_URL/api-keys/$ASSISTANT_KEY_ID/permissions" \
-H "x-api-key: $FOUNDATION4_API_KEY" \
-H "x-api-key-secret: $FOUNDATION4_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"permissions": [
{"object_type": "pipelines", "object_id": "'"$PIPELINE_ID"'", "permission": 5}
],
"classifications": ["internal"]
}'

Expected result: status 200 and an empty body.

Connection check​

The following requests check the connection with the assistant's key before any client is configured, so that a failure shows the HTTP status and the message. Start a session:

curl -i -X POST "$FOUNDATION4_URL/mcp" \
-H "x-api-key: $ASSISTANT_KEY_ID" \
-H "x-api-key-secret: $ASSISTANT_KEY_SECRET" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": "2025-11-25", "capabilities": {}, "clientInfo": {"name": "curl", "version": "1.0"}}}'

Expected result: status 200, an mcp-session-id header and an event whose result names the capabilities prompts, resources and tools. Status 401 means that the key headers are wrong, and status 403 with Forbidden: Host header is not allowed means that the deployment restricts the host names. Set the session variable and complete the initialization:

export MCP_SESSION_ID=<value of the mcp-session-id header>

curl -i -X POST "$FOUNDATION4_URL/mcp" \
-H "x-api-key: $ASSISTANT_KEY_ID" \
-H "x-api-key-secret: $ASSISTANT_KEY_SECRET" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Mcp-Session-Id: $MCP_SESSION_ID" \
-H "MCP-Protocol-Version: 2025-11-25" \
-d '{"jsonrpc": "2.0", "method": "notifications/initialized"}'

Expected result: status 202 and an empty body. List the pipelines that the key can read:

curl -X POST "$FOUNDATION4_URL/mcp" \
-H "x-api-key: $ASSISTANT_KEY_ID" \
-H "x-api-key-secret: $ASSISTANT_KEY_SECRET" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Mcp-Session-Id: $MCP_SESSION_ID" \
-H "MCP-Protocol-Version: 2025-11-25" \
-d '{"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "get_pipelines", "arguments": {}}}'

Expected result: status 200 and an event whose structuredContent holds one pipeline, support-kb, with the vector index and the full-text index in search_indexers. The key reads no other pipeline, so no other pipeline appears. End the session:

curl -i -X DELETE "$FOUNDATION4_URL/mcp" \
-H "x-api-key: $ASSISTANT_KEY_ID" \
-H "x-api-key-secret: $ASSISTANT_KEY_SECRET" \
-H "Mcp-Session-Id: $MCP_SESSION_ID"

Expected result: status 202 and an empty body.

Client configuration​

An MCP client connects to Foundation4 with the following settings:

SettingValue
TransportStreamable HTTP, which some clients name HTTP
URLThe MCP URL
Header x-api-keyThe key identifier, $ASSISTANT_KEY_ID
Header x-api-key-secretThe key secret, $ASSISTANT_KEY_SECRET

The client sends both headers with every request. A client that supports only the standard input and output (stdio) transport, or only the OAuth-based authorization of the MCP specification, cannot connect to the Foundation4 MCP server directly.

Many MCP clients read the settings from a JSON file with an entry of the following form. The name of the top-level object and of the transport field differ between clients, and the documentation of each client names them:

{
"mcpServers": {
"foundation4": {
"type": "http",
"url": "https://foundation4.example.com/mcp",
"headers": {
"x-api-key": "59971347-4b50-4edd-b6f6-12184d2af420",
"x-api-key-secret": "change-me"
}
}
}
}

The secret grants the key's access to anyone who reads the file. A configuration file that is shared or kept under version control therefore takes the secret from an environment variable or from the client's secret store, where the client supports either.

Expected result: the client reports the foundation4 server as connected and lists 18 tools, from add_document to search_knowledge. The prompts of the client list no agent, because the key holds no permission on an agent.

First question​

Ask the assistant a question that the support-kb pipeline answers, and name the knowledge base in the question:

Search the support knowledge base: how do customers get their money back?

Expected result: the client shows a call of search_knowledge with pipeline_id set to the identifier of support-kb and internal or public in classifications, and the answer states that refunds for annual plans are prorated. Before the search, the assistant usually calls get_pipelines to find the pipeline and get_pipeline_classifications to read the classifications that the key can use.

The following conditions change the result of a search through the assistant:

  • Classifications. A search that names a classification outside the key's allow-list returns an error, and the assistant usually repeats the search with the classifications that get_pipeline_classifications returns.
  • Paths. A search without a path pattern covers only the documents without a path. In a pipeline whose documents have paths, the assistant calls list_paths and names a pattern, such as kb.>, as described in Organize and search documents by path.
  • Filters. The assistant builds metadata filters from the schema that get_pipeline returns. A filter on a field that the schema does not declare returns the error Schema error.

Instructions in the client, such as a project instruction that names the pipeline and the classifications, save the discovery calls in each conversation.

Agent prompts​

An agent gives the assistant a tested prompt template for a task, such as the support-answers agent of Agents and prompt templates. Grant read and execute permission (5) on the agent:

curl -X POST "$FOUNDATION4_URL/api-keys/$ASSISTANT_KEY_ID/permissions" \
-H "x-api-key: $FOUNDATION4_API_KEY" \
-H "x-api-key-secret: $FOUNDATION4_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"permissions": [
{"object_type": "agents", "object_id": "'"$AGENT_ID"'", "permission": 5}
]
}'

Expected result: status 200 and an empty body. A grant without classifications keeps the allow-list of the existing entries.

After the client reconnects, the client lists support-answers among the prompts of the foundation4 server, usually as a command. The prompt asks for pipeline_id, classifications and question, and path for a pipeline whose documents have paths. The client sends the agent's messages, with the retrieved fragments inserted, to the assistant's own language model. The agent's run_agent tool asks a Foundation4 LLM instead, and requires permission 5 on the LLM as well.

Connection errors​

ErrorCauseResolution
HTTP 401 on every requestThe client sends no key headers, or headers with a wrong valueCheck the header names and values in the client configuration
HTTP 403 Forbidden: Host header is not allowedThe deployment restricts the host names of the MCP serverAdd the host name of the MCP URL to mcp.allowed_hosts
HTTP 404 Not Found: Session not foundThe session ended after 5 minutes without a message, the API server replica restarted, or the request reached another replicaReconnect the client. With several replicas, configure session affinity.
HTTP 406 or 415The client does not use the streamable HTTP transportSelect the streamable HTTP transport
Tool error Pipeline not foundThe key lacks read and execute permission on the pipelineGrant permission 5 on the pipeline

Manage API keys and permissions describes how to change the key's permissions and how to replace the key before the expiration date.