creative-graph
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
Creative Graph
I needed one write path for a UI and an agent. The React console and the MCP server both post to /graphql. Neither opens SQLite on its own. Creatives are CTV, video, audio, or DOOH. Budgets are integer cents.
I made this for a developer-ecosystem interview. Bad writes fail closed. Deploy is a Dockerfile, not a slide.
Why one schema
GraphiQL, the React console, and MCP tools all send createCreative, creatives, and creative. If a field is wrong, every client is wrong the same way. The MCP server does not open SQLite. It posts to /graphql. An agent with a raw database handle would skip the cents checks, the typed NOT_FOUND errors, and the SQL CHECK constraints. I did not give it that option.
Related MCP server: GenPDM MCP Server
Why cents
$1,200 is twelve hundred dollars, 120000 cents. GraphQL Int will not take $1,200 or 12.5. The console and MCP convert dollars first. The resolver still checks Number.isInteger. A float, extra fraction digits, or a junk string throws. A missing creative id on updateCreative returns extensions.code: NOT_FOUND and data: null. The field is Creative!, so the write cannot succeed as a silent null.
5-minute demo
Needs Node 22+. I checked this repo on Node 25. node:sqlite is built in, so there is no native addon.
cp .env.example .env
npm install
npm test
npm run devOpen http://127.0.0.1:5173. If that port is already taken, Vite prints the next one. You should see the seeded Spring CTV / audio pack. A 15s CTV bumper at 50000 cents, and a 30s podcast read in DRAFT at 25000 cents.
Leave the budget as
$1,200. The helper text should readSends budgetCents: 120000. Click Create. A new DRAFT creative appears.The console has two buttons for the failure cases, because walking someone through GraphiQL mid-interview is a bad demo. Click Update missing ID. The banner should show
Creative cre_does_not_exist was not found [NOT_FOUND].Click Send "$1,200" as GraphQL Int. GraphQL rejects the string before a row is written.
Open http://127.0.0.1:4000/graphql and run:
query {
campaign(id: "cmp_demo") {
name
creatives { id name format budgetCents }
}
}The schema file is schema.graphql. Tables live in src/db/migrations/001_init.sql.
How to run
What | Command | Where |
API + React |
| GraphQL at |
API only |
|
|
Built UI served by the API |
| UI and GraphQL both on |
Tests |
| schema, cents, bad-id writes, MCP input |
MCP stdio |
| talks to |
MCP tool list |
| prints |
The API must be up before MCP tools do anything useful. I left it that way so MCP cannot bypass GraphQL.
MCP in Cursor or Claude
npm run mcp:list should print three tools. Then add the server.
Cursor. Put this in ~/.cursor/mcp.json or the project .cursor/mcp.json.
{
"mcpServers": {
"creative-graph": {
"command": "npx",
"args": ["tsx", "src/mcp/index.ts"],
"cwd": "/ABS/PATH/TO/creative-graph",
"env": {
"GRAPHQL_URL": "http://127.0.0.1:4000/graphql"
}
}
}
}Claude Desktop uses the same command, args, cwd, and env under mcpServers in claude_desktop_config.json.
Tool inputs are Zod-checked before the HTTP call.
list_creativesoptionalcampaignId,formatget_creativerequiresidcreate_creativerequirescampaignId,name,format,durationMs, and exactly one ofbudgetCentsorbudget."$1,200"is valid forbudget.
Deploy
This repo is not claiming a live URL. There is no Railway, Fly, or Wrangler CLI on the machine that built it.
Railway, one service, Dockerfile.
Push the repo to GitHub.
New Railway project from that repo. Builder reads
Dockerfile/railway.toml.Set
PORT=4000if the platform does not inject it.DATABASE_PATH=/app/data/creative-graph.sqliteis already in the image.Health check is
GET /health.After deploy, GraphQL is
https://<host>/graphqland the console ishttps://<host>/.
Fly.io uses the same image. Run fly launch then fly deploy. SQLite in the container is ephemeral unless you mount a volume on /app/data.
No secrets are required for the demo. Copy .env.example. Do not commit .env.
What this is not
I skipped Go and Rails. The console is one form and a table, so I did not add Redux. I used TypeScript so GraphQL Yoga and the MCP SDK live in the same repo I run on a laptop. Multi-region ad serving and frequency caps are not here. I did not model how bids get priced. Those are honest gaps against a StackAdapt Developer Ecosystem posting. What that posting actually wants is a public API as the contract. Agents use the same write path as the UI.
This server cannot be deployed
Maintenance
Related MCP Connectors
Creative-intelligence MCP for campaign strategy, ad builds, QA, and reporting.
Google Ads MCP: reports, search terms, negatives, budgets, campaigns. Approval on every write.
Create AI images and videos, manage projects and credits, and use workspace campaign context.
Google Ads MCP with 20,000+ account peer context and staged approve-then-execute writes.
Related MCP Servers
- AlicenseBqualityBmaintenanceUnofficial Google Ads MCP for campaigns, keywords, budgets, reports and gated mutations.3074 npm4MIT
- FlicenseNot gradedqualityCmaintenanceEnables MCP clients to interact with a fixed business GraphQL API as typed, safely guarded tools, including JWT authentication, rate limiting, and query/mutation protections.-
- AlicenseBqualityBmaintenanceEnables agents to read Google Ads data and stage changes for review before applying them, with read-only defaults and guarded experimental writes.21Apache 2.0
- AlicenseAqualityCmaintenanceEnables MCP clients to retrieve Google Ads performance data, run GAQL queries and keyword planner research, and create or manage search and P-MAX campaigns, budgets, keywords, and ad status. Includes safety defaults such as paused creation and read-only mode.16MIT