Files
stripe__link-cli/scripts/sync-skill-version.js
Jason f77d7451d4 Split the Cursor plugin into plugins/cursor-link with MCP-first skills (#276)
* Split the Cursor plugin into plugins/cursor-link with MCP-first skills

Cursor reaches Link through the hosted MCP server at
api.cursor.com/rest-mcp/stripe-link/mcp, but the plugin's skills were the
CLI-oriented ones shared with Claude and Codex via a symlink to the repo
root. They told Cursor users to npm install @stripe/link-cli and to register
a second, local stdio MCP server, which conflicts with the hosted one.

Give Cursor its own self-contained plugin directory with no shared files, and
write its skills against the tools the hosted server actually exposes:
get_userinfo, list_spend_requests, get_spend_request, list_payment_methods,
list_shipping_addresses, sign_web_bot_auth, and report_agent_observation.

That server exposes no spend-request writes, so the purchase skill covers
finding and spending against a request the user already approved and stops
when none exists. Transactions, balances, and sources are not reachable yet,
so no financial-insights skill ships here; plugins/link still covers that for
CLI-based clients.

With a real .mcp.json in the new directory there is no longer a symlinked
.mcp.json to dodge, so the .link-cursor-mcp.json override is gone.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Route spend approvals through request_virtual_card

The skills described approval as something the agent could not do, which is
true of the Link MCP server but not of Cursor, where request_virtual_card
raises an approval card for exactly this. Rewrite the purchase flow around
that tool: its argument contract (cents including tax and shipping, a 7-word
title, a 100 to 140 character context, line items summing exactly to the
total), the turn ending on the call, the already-pending and denied outcomes,
and the 5/15/30/60 second poll of get_spend_request before retrieving the
card.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Call the product Link, not Stripe Link

Review feedback from @danhill-stripe on the marketplace description.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 09:12:57 -04:00

55 lines
1.6 KiB
JavaScript

#!/usr/bin/env node
import { readFileSync, writeFileSync } from 'node:fs';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
const pkg = JSON.parse(
readFileSync(resolve(root, 'packages/cli/package.json'), 'utf8'),
);
const { version } = pkg;
function syncSkillVersion(label, path) {
const content = readFileSync(path, 'utf8');
const updated = content.replace(/^version:\s*.+$/m, `version: ${version}`);
if (updated !== content) {
writeFileSync(path, updated);
console.log(`Updated ${label} version to ${version}`);
} else {
console.log(`${label} version already at ${version}`);
}
}
function syncPluginJsonVersion(label, path) {
const json = JSON.parse(readFileSync(path, 'utf8'));
if (json.version !== version) {
json.version = version;
writeFileSync(path, `${JSON.stringify(json, null, 2)}\n`);
console.log(`Updated ${label} version to ${version}`);
} else {
console.log(`${label} version already at ${version}`);
}
}
syncSkillVersion(
'SKILL.md',
resolve(root, 'skills/create-payment-credential/SKILL.md'),
);
syncSkillVersion(
'financial-insights/SKILL.md',
resolve(root, 'skills/financial-insights/SKILL.md'),
);
syncPluginJsonVersion(
'cursor-link/.cursor-plugin/plugin.json',
resolve(root, 'plugins/cursor-link/.cursor-plugin/plugin.json'),
);
syncPluginJsonVersion(
'.claude-plugin/plugin.json',
resolve(root, 'plugins/link/.claude-plugin/plugin.json'),
);
syncPluginJsonVersion(
'.codex-plugin/plugin.json',
resolve(root, 'plugins/link/.codex-plugin/plugin.json'),
);