← Back to blog

Cursor MCP Setup for Social Posting: mcp.json, Env Interpolation and Where the Key Must Not Live

·Cursor MCPmcp.jsonAI editor social postingMCP auto publishCursor remote MCP server

Cursor MCP Setup for Social Posting: mcp.json, Env Interpolation and Where the Key Must Not Live

TL;DR: Cursor reads MCP servers from mcp.json. A remote server needs only a url, plus optional headers. For posting, put the connection address in the global ~/.cursor/mcp.json (or reference an environment variable with ${env:NAME}) so it never lands in a repo, and keep Cursor’s default per-tool approval on.

You finish a feature in Cursor, and the changelog is already written in the chat. Turning that into a post for X, LinkedIn or Dev.to means leaving the editor. An MCP server that can publish removes the trip: you say “post this”, and the agent does it from the same window.

Everything about Cursor’s config below comes from Cursor’s own MCP documentation. Where I give a preference instead of a documented fact, I say so.

What the model gets

PublishPort exposes two generic tools rather than one plugin per platform. list_capabilities() reports which platforms are logged in on your machine. local_bash(cmd) runs a command there through the relay, using your own browser sessions. The model reads each command’s --help to learn its arguments. The design is explained in how an MCP server for content publishing works.

On your side: install the PublishPort desktop client, log in to the accounts you want to post from, and copy the connection address from the AI integration page. Treat the address as a credential, because it can run commands on your computer.

The mcp.json entry

Per the Cursor docs, Cursor supports three transports: stdio, SSE and Streamable HTTP. A remote relay is the HTTP kind, so the entry uses url, not command:

{
  "mcpServers": {
    "publishport": {
      "url": "<your connection address>"
    }
  }
}

If your address expects a header, the docs show the shape: a headers object next to url. Check the PublishPort docs for whether your setup needs one, since I can’t know your auth method from here.

Compared with the other CLIs I have covered, Cursor is the simple case. Gemini CLI splits url and httpUrl (see that setup), and Codex uses a TOML table with a tool timeout (see that one). In Cursor one url field covers it.

Project file or global file?

The docs give two locations: .cursor/mcp.json in a project for project-specific tools, and ~/.cursor/mcp.json for tools available everywhere.

For a publishing server I use the global file. The reason is leakage, not convenience. A .cursor/mcp.json sits inside the repo, and a careless git add . commits the address. If the repo is public, you have published a key to your machine. If it already happened, regenerate the address in the client so the old one stops working.

Keep the secret out of the file entirely

Cursor resolves variables in command, args, env, url and headers. The documented syntax includes ${env:NAME}, ${userHome} and ${workspaceFolder}. That lets a shared project file hold no secret at all:

{
  "mcpServers": {
    "publishport": {
      "url": "${env:PUBLISHPORT_MCP_URL}"
    }
  }
}

Set PUBLISHPORT_MCP_URL in your shell profile or system environment. One caveat from the docs: envFile only works for stdio servers, and for remote servers they point you to interpolation with variables set in the shell profile or system environment. A Cursor started from a launcher that doesn’t load your shell profile may not see the variable, so restart it from a terminal if the server shows as failed.

Approvals: leave the default

The docs say Cursor asks for approval before using an MCP tool by default, and you can expand the arrow beside a tool name to see its arguments. Approval follows the same run modes as terminal commands, and enterprise admins can restrict servers and tools through an allow list.

Publishing is public and hard to retract, so I keep the prompt and read the text before approving. A second look costs seconds. A wrong public post costs more. This is my preference, not a Cursor requirement.

Example: a changelog to two platforms

With the server connected, I type in the chat: “Turn the changes in this branch into a short post and publish it to Dev.to and LinkedIn.” The agent calls list_capabilities() to confirm both are online, reads each publish command’s --help, drafts the text, and asks for approval at each call. Platform details differ, which is why the per-platform notes live in automating Dev.to posts and scheduling LinkedIn posts.

If you have never let an agent publish for you, rehearse with a throwaway post first.

Limits

Checklist

FAQ

Why does Cursor show the server as failed?

Check the JSON is valid and that the address is complete. If you used ${env:...}, confirm the variable exists in the environment Cursor was launched from. Then check the desktop client is running.

Do I need OAuth?

The docs support OAuth for servers that use it, including static client credentials in an auth object. Whether your address needs it depends on the server, so follow the PublishPort docs.

Can I use the same address as in other clients?

Yes. Same address, different config format per client. See connecting AI to social media posting for the general picture.

Is it safe to share .cursor/mcp.json with a team?

Only if it holds no secret. Use ${env:...} so each person supplies their own address.

Ready to try it? See PublishPort pricing and connect your first platform.