This is Part 3 of the “Building a Monetized API” series. In Part 1, we set up the API gateway with authentication, consumer isolation, and rate limiting. In Part 2, we added meters, plans, Stripe integration, and a self-serve developer portal. Now we’re adding an MCP server on top of the same API and gating access so only paid subscribers can use it.
15:23Building a Monetized API, Part 3
Watch the video walkthrough of adding an MCP server and gating access to paid plan subscribers with custom code.
Why gate MCP access behind a paid plan?
In Part 2, we set up three subscription tiers: Free, Starter, and Pro. The
Starter and Pro plans include a boolean feature called mcp_server with an
entitlement set to true. The Free plan doesn’t have it.
This is a deliberate product decision. The API itself is available on every plan (with different usage limits), but MCP server access is a premium feature. Offering AI-powered tooling as a paid upgrade is a natural way to add value to higher tiers without changing the underlying API at all.
- You have an existing Zuplo project with monetization already configured (see Part 2)
- You want to expose your API as an MCP server that AI assistants can use
- You need to restrict MCP access to specific subscription tiers using entitlements
Step 1: Adding the MCP server
Zuplo has native MCP server support built into the gateway. Adding one takes about 30 seconds.
Go to your project’s route list and click the Add tab. You’ll see an MCP Server option. Select it, and configure the basics:
- Name:
ChangeLoggle MCP Server - Version:
0.0.1 - Description:
Create, update, and discover team changelog info.
That creates the MCP server endpoint at /mcp on your gateway.

MCP Servers with Zuplo
Learn how to turn your existing API gateway into a toolset that AI systems can discover and use.
Step 2: Selecting which routes to expose as tools
After creating the MCP server, you need to choose which API routes become MCP tools. Click Select Tools to see all available routes.
You can be selective here. If you only want a read-only MCP experience, pick just the GET endpoints. If you want full read-write access (create projects, update changelogs, search entries), select everything.
For our changelog API, we’re exposing all 12 endpoints as tools. Every operation that’s available via the REST API is also available through MCP.
Be thoughtful about this in your own projects. Each tool adds to the context that AI assistants need to process. If you have dozens of endpoints, ask yourself whether all of them make sense as MCP tools, or whether a focused subset delivers a better experience.
Click Update Tools to save your selection.

Step 3: Testing the MCP server
Before adding access controls, verify that the MCP server works. You can test it with any MCP client. In the video, we use MCP Jam, but any compatible client works.
To connect:
- Use your gateway’s deployment URL with
/mcpappended as the endpoint - Set the connection type to HTTP
- Set authentication to Bearer Token and paste in an API key from the developer portal
If the connection succeeds, you can interact with your API through the MCP client. Try asking it to list projects or create a new one. Every request flows through the same gateway, uses the same API key authentication, and hits the same origin API.
At this point there’s no entitlement check on the MCP route, so any valid API key works regardless of plan. That’s fine for testing. We’ll lock it down in the next step.

Step 4: Writing the access check policy
To gate MCP access, we need a custom inbound policy that inspects the subscriber’s entitlements and blocks the request if they don’t have MCP access.
The key is the MonetizationInboundPolicy class from @zuplo/runtime. Because
the MonetizationInbound policy runs
before this custom code, it has already authenticated the API key and loaded the
subscriber’s plan data. Calling
MonetizationInboundPolicy.getSubscriptionData(context) gives you the full
subscription context for the current consumer, including their entitlements.
Create a new module in your Zuplo project called check-mcp-access:
Here’s what’s happening:
MonetizationInboundPolicy.getSubscriptionData(context)retrieves the subscription for the consumer making the request. The MonetizationInbound policy that runs before this code has already authenticated the API key and populated the context with subscription data.- The code checks
subscription.entitlements.mcp_server.hasAccess. Themcp_serverkey matches the feature we set up in Part 2 when configuring the Starter and Pro plans. Entitlements are accessed as properties on theentitlementsobject, keyed by the feature’s identifier. - If the entitlement doesn’t exist (Free plan) or
hasAccessisfalse, the request gets a 403 JSON response telling the consumer to upgrade. - If the entitlement exists and
hasAccessistrue, the request passes through to the MCP server handler.
Monetization Inbound Policy
Full policy reference including metering options, subscription data access, and exposed functions.
Step 5: Wiring the policies to the MCP endpoint
Unlike the policies we added in Parts 1 and 2 (which apply to every route), the
MCP access check only needs to go on one endpoint: the /mcp route.
Open the MCP server route and add two inbound policies in this order:
- Monetization Inbound (existing policy): handles API key authentication and request metering. This needs to run first so the consumer’s identity and subscription are available to downstream policies.
- Custom Code Inbound pointing to
check-mcp-access: runs the entitlement check we just wrote.
The Custom Code Inbound policy just needs to point at the module:
Save and deploy. The MCP endpoint now authenticates the request, meters it, and checks entitlements before the MCP server handler ever runs.
Custom Code Inbound Policy
Write custom request handling logic that runs as part of your policy pipeline.
Step 6: Testing the access gate
With the policies in place, we can verify that free-plan subscribers are blocked and paid-plan subscribers get through.
Free plan test. Connect an MCP client using an API key from a free-plan subscription. The connection attempt fails with a 403 and the message telling the consumer to upgrade. The MCP server never processes the request.

Paid plan test. Either upgrade the same subscription to Starter or Pro through the developer portal, or use an API key from an existing paid subscription. Nothing changes about the connection setup: same URL, same API key. This time, the connection succeeds and the MCP client can list tools and make requests.

The API key itself doesn’t change when a subscriber upgrades plans. The entitlement check happens at request time against the current subscription data, so the moment someone upgrades, their existing API key starts working with the MCP server.
What we built in Part 3
The monetized API now has an MCP server with plan-gated access:
- MCP server added to the gateway with all API routes exposed as tools
- Custom access policy using
MonetizationInboundPolicy.getSubscriptionDatato check entitlements - Free plan subscribers blocked from MCP access with a clear upgrade message
- Paid plan subscribers (Starter and Pro) get full MCP server access
- MCP requests are metered the same way as standard API requests
The MCP server sits on a single endpoint, so the access check only needed to be added once. Every other route in the project continues to work exactly as before. And because the MonetizationInbound policy handles both authentication and metering, MCP requests count toward the subscriber’s usage just like any other API call.
What’s next
In Part 4, we’ll finish the developer portal. Right now it has the default documentation that Zuplo generates from the OpenAPI spec, but it needs polish: better descriptions, branded styling, and a layout that makes the API easy to explore. That’s the last step before this is production-ready.
