Skip to content

Connect an agent with MCP

A finance lead wants Codex to help review the Main Campus ledger without giving it a browser login or access to another organization. She creates an expiring integration key with only the required reads, connects the MCP endpoint and checks the returned workspace identity before requesting any accounting data.

MCP (Model Context Protocol) lets a compatible agent discover tools, read resources and use prompts. Schoolbooks serves stateless Streamable HTTP at /api/v1/mcp. Every request rechecks the key and live access; the agent cannot choose its own tenant or organization.

On this pageChoose Spark or an external agentBefore you beginCreate a key for the intended workspaceRegister the server in CodexConfigure the API-key headerSupply the secret and start CodexVerify the connection before reading recordsConnect from a TypeScript SDK clientWhat tools can doTroubleshoot connection and access errorsRotate, revoke or change scopeReferences and next steps

Choose Spark or an external agent

UseAuthenticationStart here
Spark inside SchoolbooksYour signed-in account and current workspaceOpen the Spark chat control in the top bar.
Codex or another custom-header MCP clientAn expiring X-API-Key integration credentialFollow this guide and verify the context resource.
An OAuth-only MCP hostNot supported by the current custom-key transportUse a client that can send custom HTTP headers.

Before you begin

  • An active Schoolbooks user, account membership and workspace membership, with permission to manage integration keys.
  • The intended modules enabled and available under the account subscription.
  • A compatible Codex installation or MCP SDK client that can send the X-API-Key header.
  • A deployment containing the MCP endpoint and platform migrations. For local development, run the API at http://localhost:3001.

Create a key for the intended workspace

The key is pinned to its owning user, account, workspace and organization. Its grants do not bypass the owner’s live access. If membership is suspended, access is removed, or the workspace’s organization binding changes, authentication or the requested action fails rather than moving the key into another scope.

  1. Sign in to Schoolbooks with your own account and select the intended organization and workspace.
  2. Open Settings → Security and find API keys. Choose Create API key.
  3. Give it a purpose-specific name, such as Main Campus Codex ledger review, and choose an expiry.
  4. Select only needed permissions. accounts.read and workspaces.read support orientation; add organizations.read or accounting.read when those reads are needed.
  5. For an integration that needs your full available API access, choose Select all. It includes permissions hidden by search; Clear removes the selection. The server still checks every grant against your current workspace access.
  6. Create the key and store the one-time secret in your secret manager. Do not put it in a chat, screenshot, repository, URL or shared document.
Select all chose 138 currently available permissions in the local demo form. Clear was then used and the dialog cancelled; no key was issued.1 Select all available user-scoped permissions2 Clear the draft selection3 Set an integration purpose before creating a key

Register the server in Codex

Run this command to add the hosted endpoint. It registers the URL; it does not configure our required custom authentication header. For local development replace the URL with http://localhost:3001/api/v1/mcp.

bash

codex mcp add schoolbooks --url https://api.schoolbooks.ke/api/v1/mcp

Configure the API-key header

Open ~/.codex/config.toml and merge the following into the existing schoolbooks entry. Do not create a second table with the same name. Only the environment variable name belongs in this file; keep the secret itself outside source control.

toml

[mcp_servers.schoolbooks]
url = "https://api.schoolbooks.ke/api/v1/mcp"
env_http_headers = { "X-API-Key" = "SCHOOLBOOKS_API_KEY" }

Supply the secret and start Codex

Provide SCHOOLBOOKS_API_KEY through your secret manager or the environment inherited by the Codex process. In a temporary Bash terminal, the following prompts without putting the typed secret into shell history. Start Codex from that same terminal. A desktop application launched elsewhere will not automatically inherit that terminal’s environment.

bash

read -rsp 'Schoolbooks API key: ' SCHOOLBOOKS_API_KEY
export SCHOOLBOOKS_API_KEY
codex

Verify the connection before reading records

A key with accounting.read still needs an enabled Accounting module and the owner’s current permission. An empty tool list can reflect access or entitlement restrictions rather than a broken transport. The orientation prompt explains the connection but cannot grant authority.

  1. Open /mcp in Codex and confirm that schoolbooks connected and its tools were discovered.
  2. Ask: “Read schoolbooks://context/current. Show the authorized user, account, workspace, organization and effective permissions. Do not change anything.”
  3. Compare the returned identifiers to the workspace you selected when creating the key. Stop if they are not the intended scope.
  4. Ask the agent to list its available Schoolbooks tools, then use a discovered accounting read to retrieve a small ledger-account or journal-register page.
  5. For a real review, give the reporting period and record reference. Open the source record in Schoolbooks to verify the result.

Connect from a TypeScript SDK client

Install the official @modelcontextprotocol/sdk package in your integration project. Set SCHOOLBOOKS_MCP_URL to the complete endpoint URL and SCHOOLBOOKS_API_KEY to the scoped secret. This client initializes the protocol and reads identity before any domain operation.

typescript

import { Client } from '@modelcontextprotocol/sdk/client/index.js'
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'

const endpoint = process.env.SCHOOLBOOKS_MCP_URL
const apiKey = process.env.SCHOOLBOOKS_API_KEY
if (!endpoint || !apiKey) throw new Error('Configure MCP URL and API key')

const client = new Client({ name: 'school-review', version: '1.0.0' })
try {
  await client.connect(new StreamableHTTPClientTransport(new URL(endpoint), {
    requestInit: { headers: { 'X-API-Key': apiKey } },
  }))
  const context = await client.readResource({ uri: 'schoolbooks://context/current' })
  const discovered = await client.listTools()
  // Verify context and use only a discovered tool with its declared schema.
  // Treat identity and domain results as private; do not send them to logs.
} finally {
  await client.close()
}

What tools can do

Tool discovery is filtered by permissions, credential policy, installed modules and subscription. Execution checks the same authoritative policy again. A REST operation is not automatically an MCP tool, and interactive-user access does not imply that an API key may perform the same write.

Remote key management and session-only actions are unavailable. An operation requiring a server-approved human approval cannot be enabled by a prompt, an approved=true argument or an agent approving its own request. Financial posting restrictions remain enforced.

Tools return declared input/output schemas. Object outputs remain objects, lists use a records wrapper, and nullable or scalar results use a result wrapper. A tool can report isError even when HTTP returns 200; inspect the tool result before treating an action as complete.

Troubleshoot connection and access errors

SymptomCheck
404 at the endpointConfirm the complete /api/v1/mcp path, intended host, deployed release and proxy routing.
401 / MCP_API_KEY_REQUIREDSet the secret in the environment used to launch the client. Send X-API-Key only; remove Authorization. Check expiry, rotation and revocation.
403 or scope mismatchCheck live membership, permissions, subscription and the pinned organization. Do not add tenant or organization overrides.
Browser Origin rejectedUse a trusted integration or ask the operator to allow the exact required browser origin. Do not disable origin checks.
No domain tool appearsCheck the owner’s permissions, key grants, enabled modules and whether that capability supports API keys and MCP.
400 / 406 / 415 with raw HTTPUse a compatible SDK. Streamable HTTP requires JSON and Accept negotiation for application/json and text/event-stream.
GET or DELETE returns 405This stateless endpoint handles MCP through POST. It does not offer a persistent session or standalone GET event stream.
HTTP 200 but a tool failedInspect isError and the tool message. Check the source record before retrying a possible mutation.

Rotate, revoke or change scope

  1. Open Settings → Security → API keys using your signed-in browser session.
  2. To replace a key in the current UI, create another key with the intended scope and permissions. Store its one-time secret, update the integration and verify the connection.
  3. Revoke the old key to end its access after replacing it. For a suspected compromise, revoke it immediately before replacement. Removing a local Codex configuration does not revoke the server-side credential.
  4. For a different workspace or organization, create a separately scoped key in that workspace rather than changing selectors in the client.

References and next steps