@blockrun/franklin 3.3.1 → 3.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -96,8 +96,28 @@ function migrateMcp(source) {
96
96
  // Claude Code format: { mcpServers: { name: { command, args, env } } }
97
97
  // Franklin format: { mcpServers: { name: { transport, command, args, label } } }
98
98
  const servers = {};
99
+ const skipped = [];
99
100
  if (raw.mcpServers) {
100
101
  for (const [name, config] of Object.entries(raw.mcpServers)) {
102
+ // Skip MCP servers that require external credentials (OAuth, API keys,
103
+ // tokens) — importing them causes noisy startup errors because the
104
+ // credentials aren't available in Franklin's context. Users can add
105
+ // these manually via ~/.blockrun/mcp.json if they set up the credentials.
106
+ const configStr = JSON.stringify(config).toLowerCase();
107
+ const needsCredentials = configStr.includes('oauth') ||
108
+ configStr.includes('credential') ||
109
+ configStr.includes('api_key') ||
110
+ configStr.includes('api-key') ||
111
+ configStr.includes('token') ||
112
+ name.includes('calendar') ||
113
+ name.includes('gmail') ||
114
+ name.includes('google') ||
115
+ name.includes('slack') ||
116
+ name.includes('notion');
117
+ if (needsCredentials) {
118
+ skipped.push(name);
119
+ continue;
120
+ }
101
121
  servers[name] = {
102
122
  transport: config.transport || 'stdio',
103
123
  command: config.command,
@@ -123,7 +143,11 @@ function migrateMcp(source) {
123
143
  };
124
144
  fs.mkdirSync(BLOCKRUN_DIR, { recursive: true });
125
145
  fs.writeFileSync(target, JSON.stringify(merged, null, 2));
126
- console.log(chalk.green(` ✓ ${Object.keys(servers).length} MCP server(s) imported`));
146
+ const importedCount = Object.keys(servers).length;
147
+ console.log(chalk.green(` ✓ ${importedCount} MCP server(s) imported`));
148
+ if (skipped.length > 0) {
149
+ console.log(chalk.dim(` · ${skipped.length} skipped (need credentials): ${skipped.join(', ')}`));
150
+ }
127
151
  }
128
152
  function migrateInstructions(source) {
129
153
  // Read CLAUDE.md and convert key preferences to learnings
@@ -86,6 +86,34 @@ export function loadMcpConfig(workDir) {
86
86
  catch {
87
87
  // Ignore corrupt project config
88
88
  }
89
+ // Filter out servers whose required credential files are missing.
90
+ // This prevents noisy startup errors from MCP servers that were imported
91
+ // (e.g. via `franklin migrate`) but don't have credentials configured yet.
92
+ // The server stays in the config file — it just gets auto-disabled until
93
+ // the user provides the credentials.
94
+ for (const [name, config] of Object.entries(servers)) {
95
+ if (config.disabled)
96
+ continue;
97
+ const env = (config.env || {});
98
+ const args = (config.args || []);
99
+ const configStr = JSON.stringify(config).toLowerCase();
100
+ // Check if any env var points to a file that doesn't exist
101
+ let missingFile = false;
102
+ for (const [, val] of Object.entries(env)) {
103
+ if (typeof val === 'string' && (val.endsWith('.json') || val.endsWith('.key') || val.endsWith('.pem'))) {
104
+ if (!fs.existsSync(val)) {
105
+ missingFile = true;
106
+ break;
107
+ }
108
+ }
109
+ }
110
+ // Check for common credential-dependent patterns in config
111
+ const needsAuth = missingFile ||
112
+ (configStr.includes('oauth') && !args.some(a => fs.existsSync(a)));
113
+ if (needsAuth) {
114
+ servers[name].disabled = true;
115
+ }
116
+ }
89
117
  return { mcpServers: servers };
90
118
  }
91
119
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blockrun/franklin",
3
- "version": "3.3.1",
3
+ "version": "3.3.2",
4
4
  "description": "Franklin — The AI agent with a wallet. Spends USDC autonomously to get real work done. Pay per action, no subscriptions.",
5
5
  "type": "module",
6
6
  "exports": {