Model Context Protocol (MCP)
Model Context Protocol (MCP) is an open-source standard that enables AI applications to connect with external systems in a unified way.
MCP allows AI models to access and interact with external data sources, APIs, and services, empowering developers to build more powerful and flexible AI solutions that leverage a wide range of external capabilities.
Learn more on the official MCP website.
Exposing MCP Tools in Neos
Neos enables you to expose MCP tools securely and selectively. All Web APIs can be made available as MCP tools, allowing AI models to interact with them seamlessly.
Exposing an entity view as an MCP Tool
To expose an entity view as an MCP tool in Neos Studio:
- Open the entity view editor.
- Check the Expose as MCP option.
- Select which entity view methods should be available for the MCP tool (none are selected by default).
Available Methods:
get: Retrieve a single entity by its identifier.getAll: Retrieve all entities of a specific type.create: Create a new entity.update: Update an existing entity.delete: Delete an entity by its identifier.
After exposing the MCP tool, you can configure its settings:
Tool Name
By default, the tool name matches the controller method name. You can change it to something more descriptive if desired.
Tool Description
The description helps AI models understand the tool's purpose. By default, it is generated from the entity view route description, but you can customize it to provide more details.
Exposing a server method as an MCP Tool
To expose a server method as an MCP tool in Neos Studio:
- Open the server method's advanced editor (tab: Artificial Intelligence).
- Check the Expose as MCP option.
- Configure the tool name and description as you would for entity views.
- Optionally, define a description for each parameter to provide additional context.
Tool Name
By default, the tool name matches the server method name. You can change it to something more descriptive if needed.
Tool Description
The description helps AI models understand the tool's purpose. By default, it is generated from the server method description or name, but you can customize it for more detail.
Parameter Descriptions
You can add descriptions for each parameter to provide context and help AI models use them effectively. By default, no parameter descriptions are set.
Configuring the MCP Endpoint
By default, the MCP endpoint is available at /api/mcp. You can change this endpoint in your cluster configuration file:
AI:
McpUrlPattern: /api/v1/mcp
In production, you can also set the endpoint using the environment variable:
AI__McpUrlPattern
Viewing and Testing Exposed MCP Tools
You can use MCP Inspector, a third-party tool, to view and test your exposed MCP tools.
To install and run MCP Inspector (requires Node.js v22.7.5 or higher):
npx @modelcontextprotocol/inspector
Configure MCP Inspector with the following settings:
- Transport Type: Streamable HTTP
- URL:
https://localhost/neos/[Your_Cluster_Name]/api/mcp - Connection Type: Direct
Click Connect to view and test the list of exposed MCP tools.
Connecting from an authenticated MCP client
When the cluster is protected by an identity provider (for example Azure AD B2C), an external MCP client such as Claude Code has to authenticate before it can use the MCP endpoint. The cluster's MCP endpoint automatically:
- advertises the real authorization server to the client through the standard OAuth discovery documents (
/.well-known/oauth-protected-resourceand/.well-known/oauth-authorization-server), so the client does not have to guess an authorization endpoint on the cluster's own host; - proxies the token endpoint (
/oauth/token) so an MCP client — a public OAuth client using PKCE, with no client secret — can redeem its authorization code even when the identity provider's discovery document does not advertise support for public clients (a known limitation of Azure AD B2C custom policies).
Warning
Authenticated MCP access requires the cluster to be hosted on Kestrel and is not compatible with HttpSys (the default web server on Windows). HttpSys enforces its registered URL prefix at the OS level and rejects a .well-known discovery request before it ever reaches the application, because the request does not carry the prefix the cluster is mounted under (for example HttpSys's default http://localhost/neos) — RFC 8414/9728 place .well-known right after the host, ahead of any such prefix. No application-level configuration can work around this. Run the cluster with --webserver Kestrel for any scenario where an MCP client needs to authenticate.
Prerequisite: a dedicated public client application
The MCP client must authenticate with its own App Registration, configured as a public client and distinct from the cluster's own (confidential) web login client. See Configure MCP client authentication for the Azure AD B2C setup, and McpScopes for the cluster-side scope configuration.
Configuring Claude Code
Register the cluster's MCP endpoint as an MCP server, providing the public client's application ID and a fixed callback port matching the loopback redirect URI registered in Azure. Run the cluster with neos run --webserver Kestrel and use its own https://localhost:[PORT] URL — not the shared HttpSys host (see the warning above):
claude mcp add --transport http --scope local --client-id [MCP_CLIENT_ID] --callback-port [CALLBACK_PORT] [SERVER_NAME] https://localhost:[PORT]/[Your_Cluster_Name]/api/mcp
Replace :
[MCP_CLIENT_ID]with theApplication (client) IDof the dedicated public client application.[CALLBACK_PORT]with the port of the loopback redirect URI registered for that application (for example5001). Without this flag, Claude Code picks a random port on every attempt, which the identity provider rejects since only the registered port is allowed.[SERVER_NAME]with a name of your choice for this MCP server.[PORT]with the Kestrel port the cluster is listening on (thehttps://one passed toneos run --urls).[Your_Cluster_Name]with your cluster name.
Then start the authentication flow:
claude mcp login [SERVER_NAME]
This opens a browser to complete the sign-in. Once authenticated, claude mcp get [SERVER_NAME] should report a Connected status.
Connecting to a multitenant cluster
On a multitenant cluster, the tenant identifier is inserted as its own URL segment, immediately before the endpoint path — the same convention already used for the cluster's own web pages (https://mycluster.example.com/[TENANT_IDENTIFIER]/). The MCP endpoint follows the same rule:
claude mcp add --transport http --scope local --client-id [MCP_CLIENT_ID] --callback-port [CALLBACK_PORT] [SERVER_NAME] https://localhost:[PORT]/[Your_Cluster_Name]/[TENANT_IDENTIFIER]/api/mcp
Replace [TENANT_IDENTIFIER] with the identifier of the tenant to connect to (as listed by the tenant selection endpoint, GET ./tenant-selection/tenants, or your own custom tenant selection page) — the other placeholders are the same as above. The tools exposed by the MCP endpoint then operate within that tenant's data, exactly as if a user had authenticated and selected that tenant through the regular web application.
Connecting to a cluster authenticated with NeosDevAuth
The steps above are written for Azure AD B2C, but the same proxied discovery and token endpoints work with any authority, including the standard development server (Preset: NeosDevAuth). The setup is actually simpler there, since NeosDevAuth's default client has no client secret and no registered redirect URI:
- skip Prerequisite: a dedicated public client application entirely — the cluster's own
Authentication:ClientId(localhostunless configured otherwise) is already a public client, since NeosDevAuth never issues it a client secret; --callback-portis not required — NeosDevAuth does not validate the redirect URI, so the random callback port Claude Code otherwise picks on every attempt is accepted;Authentication:McpScopesdoes not need to be configured either — the emptyscopes_supportedthis produces only matters for Azure AD B2C, which rejects an authorization request with no scope (error AADB2C90010).
claude mcp add --transport http --scope local --client-id [CLIENT_ID] [SERVER_NAME] https://localhost:[PORT]/[Your_Cluster_Name]/api/mcp
Replace [CLIENT_ID] with the cluster's Authentication:ClientId (localhost unless configured otherwise), and [SERVER_NAME], [PORT], [Your_Cluster_Name] as described above. The cluster still has to run on Kestrel (see the warning above, which applies regardless of the authentication provider). Then start the authentication flow the same way with claude mcp login [SERVER_NAME].