feat: add .env and Claude config downloads to API key reveal
After creating a key, two download buttons appear: - 'Download .env' — pre-filled FABLE_URL + FABLE_API_KEY - 'Download Claude config' — ready-to-paste mcpServers JSON block Also adds Future Task A (in-app install instructions) and Future Task B (Forgejo MCP) to the implementation plan. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2057,3 +2057,33 @@ Ask Claude: "Use Fable to list my projects." Verify a real response comes back.
|
|||||||
git add fable-mcp/
|
git add fable-mcp/
|
||||||
git commit -m "feat: fable-mcp v0.1.0 — complete MCP server with all tool groups"
|
git commit -m "feat: fable-mcp v0.1.0 — complete MCP server with all tool groups"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Future Tasks (post v0.1.0)
|
||||||
|
|
||||||
|
### Future Task A: In-app MCP install instructions (PyPI/Forgejo registry)
|
||||||
|
|
||||||
|
Once `fable-mcp` is published to a package registry (PyPI or the Forgejo package registry at `git.fabledsword.com`), add an install instructions panel to the API Keys tab in Settings. This replaces manual `pip install -e` with a one-liner and links the version shown to the package registry.
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `frontend/src/views/SettingsView.vue` — add "Install" section above the create form showing:
|
||||||
|
- `pip install fable-mcp` (or registry-specific command)
|
||||||
|
- Current published version badge (fetched from registry API)
|
||||||
|
- Link to full documentation/README
|
||||||
|
|
||||||
|
**Depends on:** fable-mcp extracted to its own Forgejo repo and published as a package.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Future Task B: Forgejo MCP server
|
||||||
|
|
||||||
|
A second MCP server (`forgejo-mcp/`) that gives Claude direct access to the Forgejo instance at `git.fabledsword.com` for CI/CD automation. Capabilities: list/create/merge PRs, trigger CI runs, read build logs, manage releases, push config files.
|
||||||
|
|
||||||
|
**Scope:** Separate spec + plan session. Key questions to resolve in brainstorming:
|
||||||
|
- Authentication: Forgejo personal access token vs. OAuth app
|
||||||
|
- Which Gitea/Forgejo API endpoints to expose as tools
|
||||||
|
- Whether to use an existing `gitea-mcp` or build from scratch (check Forgejo's MCP compatibility)
|
||||||
|
- CI automation: trigger builds, read job logs, manage runner labels
|
||||||
|
|
||||||
|
**Prerequisite:** fable-mcp v0.1.0 working and registered in Claude Code.
|
||||||
|
|||||||
@@ -94,6 +94,38 @@ async function copyApiKey() {
|
|||||||
setTimeout(() => { apiKeyCopied.value = false; }, 2000);
|
setTimeout(() => { apiKeyCopied.value = false; }, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _downloadFile(filename: string, content: string, mimeType = 'text/plain') {
|
||||||
|
const blob = new Blob([content], { type: mimeType });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = filename;
|
||||||
|
a.click();
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
function downloadEnvFile() {
|
||||||
|
const baseUrl = window.location.origin;
|
||||||
|
const content = `FABLE_URL=${baseUrl}\nFABLE_API_KEY=${newKeyValue.value}\n`;
|
||||||
|
_downloadFile('fable-mcp.env', content);
|
||||||
|
}
|
||||||
|
|
||||||
|
function downloadMcpConfig() {
|
||||||
|
const baseUrl = window.location.origin;
|
||||||
|
const config = {
|
||||||
|
mcpServers: {
|
||||||
|
fable: {
|
||||||
|
command: 'fable-mcp',
|
||||||
|
env: {
|
||||||
|
FABLE_URL: baseUrl,
|
||||||
|
FABLE_API_KEY: newKeyValue.value,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
_downloadFile('fable-mcp-config.json', JSON.stringify(config, null, 2), 'application/json');
|
||||||
|
}
|
||||||
|
|
||||||
// Groups management
|
// Groups management
|
||||||
const groups = ref<GroupEntry[]>([]);
|
const groups = ref<GroupEntry[]>([]);
|
||||||
const groupsLoading = ref(false);
|
const groupsLoading = ref(false);
|
||||||
@@ -1537,7 +1569,11 @@ function formatUserDate(iso: string): string {
|
|||||||
<code class="api-key-value">{{ newKeyValue }}</code>
|
<code class="api-key-value">{{ newKeyValue }}</code>
|
||||||
<button @click="copyApiKey" class="btn btn-secondary btn-sm">{{ apiKeyCopied ? 'Copied!' : 'Copy' }}</button>
|
<button @click="copyApiKey" class="btn btn-secondary btn-sm">{{ apiKeyCopied ? 'Copied!' : 'Copy' }}</button>
|
||||||
</div>
|
</div>
|
||||||
<button @click="newKeyValue = ''" class="btn btn-secondary" style="margin-top: 0.5rem;">Done</button>
|
<div style="display:flex; gap:0.5rem; margin-top: 0.5rem;">
|
||||||
|
<button @click="downloadEnvFile" class="btn btn-secondary btn-sm">Download .env</button>
|
||||||
|
<button @click="downloadMcpConfig" class="btn btn-secondary btn-sm">Download Claude config</button>
|
||||||
|
<button @click="newKeyValue = ''" class="btn btn-secondary">Done</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Keys table -->
|
<!-- Keys table -->
|
||||||
|
|||||||
Reference in New Issue
Block a user