Half the data I need while coding does not live in the repo. Seed rows, the pricing table, a small feature-flag list, the copy a non-technical teammate owns. All of it sits in a Google Sheet, and every time the editor's agent needed a value from it I was tabbing over, copying a block of cells, and pasting it into the chat. That works once. By the fourth time it is just a tax on getting anything done.

The fix is to let the editor read the sheet itself. MCP, the Model Context Protocol, is the standard way an AI client connects to an outside data source: the server hands the agent a small set of tools, and the agent decides when to call them. VS Code, Cursor, and Windsurf all speak it natively, so none of them need a plugin or a local process to talk to one.

What they do need is a server to point at. PasteSheet takes a Google Sheet you have shared with "Anyone with the link" and hosts it as an MCP endpoint, which is just a URL a client can connect to. There is no Google Cloud project, no OAuth consent screen, and no service-account JSON. This post is that URL dropped into all three editors, plus the one difference between their config files that cost me twenty minutes.

One URL, three config files

Each connected sheet gets its own MCP URL, shaped like https://pastesheet.com/mcp/sheets/your-endpoint-id. The transport is plain streamable HTTP, so there is nothing to install and nothing running on your machine.

The framing that matters here is publish, don't connect. Most tools want you to connect your whole Google account to the editor, behind OAuth and a Cloud project you configure yourself, which hands the agent far more than the one sheet you care about. Publishing goes the other way: one sheet becomes one endpoint, and the agent can read that sheet and nothing else in your Drive.

Once connected, the agent gets three read-only tools. list_tabs shows the tabs in the sheet, get_schema shows each column's name and inferred type, and query_rows reads rows with filters, sorting, and pagination. The middle one carries more weight than it looks. An agent that does not know your real column names guesses them, and half its queries come back empty. When it can read the schema first, it writes queries against the actual columns and they land on the first try.

Now the configs. Same server, same URL, three files that disagree about how to describe it.

VS Code and Copilot agent mode

VS Code reads MCP servers from .vscode/mcp.json in your workspace, or from your user-level configuration if you want the sheet available everywhere. Create the file and paste your endpoint's URL:

{
  "servers": {
    "pastesheet": {
      "type": "http",
      "url": "https://pastesheet.com/mcp/sheets/your-endpoint-id"
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

Two things are specific to VS Code. The top-level key is servers, not mcpServers, and the transport is declared explicitly with "type": "http". Then open Copilot Chat and switch to Agent mode. Ask mode will not call tools, so if the sheet seems invisible that is usually why. In agent mode Copilot discovers the tools, reads the schema, and queries only the rows it needs. You never name a tool yourself.

Cursor

Cursor reads from ~/.cursor/mcp.json globally, or .cursor/mcp.json for a single project. You can also go through Cursor Settings → MCP → Add new MCP server if you would rather not touch the file:

{
  "mcpServers": {
    "pastesheet": {
      "url": "https://pastesheet.com/mcp/sheets/your-endpoint-id"
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

Here the top-level key is mcpServers and there is no transport line at all. Cursor infers HTTP from a bare url. After saving, the settings panel should list list_tabs, get_schema, and query_rows under the server. If the tool list is empty, the config did not parse. The Cursor setup guide has the longer version, including how to pass a key for a private endpoint.

Windsurf and Cascade

Windsurf's Cascade agent supports MCP natively too. Open its MCP settings or edit mcp_config.json directly:

{
  "mcpServers": {
    "pastesheet": {
      "serverUrl": "https://pastesheet.com/mcp/sheets/your-endpoint-id"
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

Look closely. The key is serverUrl, not url. Windsurf is the only one of the three that spells it that way, and this is the twenty minutes I mentioned. I copied my working Cursor block over, changed nothing, and Cascade showed no tools and no error. Not a failed connection, not a warning, just an empty tool list that looks identical to a server that has not been added yet. The Windsurf guide spells the block out if you want to check yours against it.

That silent failure is the real reason this post exists. Three editors, one protocol, and three JSON dialects where a wrong key produces nothing to debug. If you would rather not hold the differences in your head, the MCP config generator emits the correct block and the correct file path for each client. Paste a sheet URL, copy the one you need.

Actually using it

With the server registered you just ask, and the agent reaches for the tools when it needs data. A real exchange against a pricing sheet, in Cursor:

Me:     Does the Starter plan include the search widget? Check the pricing sheet.
Agent:  [calls get_schema, sees columns: plan, feature, included]
        [calls query_rows filter plan=Starter, feature=search widget]
        No. Search is Pro and above. Starter includes the API and MCP only.

Enter fullscreen mode Exit fullscreen mode

I did not name a column or a tool. The useful part is that this happens mid-task, without leaving the editor: confirm a value, cross-reference a config table, check that a field actually exists before writing code against it.

Where it stops

The connection is read-only. There is no write tool in the set, so the agent can query and analyse the sheet but can never change it. If you want an agent that logs results back or updates a status column, this is the wrong tool and no framing fixes that.

Rows are cached for a window you choose, so an edit you made thirty seconds ago may not appear until the cache refreshes. That is what keeps an agent's tenth query from hitting Google, which matters because the Sheets API allows only 60 reads per minute per user before it starts returning 429. It is still a trade, and you should know it is there.

On cost, MCP is included on the free plan for public endpoints. Private endpoints and the account-wide workspace server at https://pastesheet.com/mcp, which exposes every sheet you own through one connector instead of one per sheet, need a paid plan from Starter at $9/mo. Full-text search and aggregation through query_rows are Pro.

The last limit is the one people miss. This whole approach works because the sheet is shared with "Anyone with the link," and PasteSheet reads it through that link rather than logging into your Google account. A private endpoint puts a bearer key in front of your PasteSheet URL, which gates who can query the endpoint. It does not gate the spreadsheet. Anyone holding the sheet's share link can still open it directly, so do not put genuinely sensitive data in a link-shared sheet.

For the ordinary case, letting your editor read a spreadsheet a teammate maintains, it is about five minutes of work and one JSON block. Just check which key your editor wants.


I build PasteSheet. Share a Google Sheet, paste the URL, and your editor gets a cached JSON API plus a read-only MCP server it can query. Free tier, no credit card, no Google Cloud project. If your client uses a config shape I did not cover, drop it in the comments and I will add it.