Skip to main content
Glama
dynamic-token-example.md12.5 kB
# 动态 Token 使用示例 ## 基础示例 ### 示例 1:使用默认 Token ```typescript // 场景:个人开发,使用配置文件中的 token // .env 文件 GITEA_BASE_URL=https://gitea.ktyun.cc GITEA_API_TOKEN=your_personal_token // 调用时不需要传 token gitea_issue_list() // 自动使用配置中的 token gitea_repo_list() // 自动使用配置中的 token gitea_issue_create({ title: "新功能开发", body: "需要实现用户管理功能" }) // 自动使用配置中的 token ``` ### 示例 2:使用临时 Token ```typescript // 场景:需要使用不同用户的权限执行操作 // 用户 A 的 token const userA_token = "glpat-aaaaaaaaaaaaaaaa"; // 用户 B 的 token const userB_token = "glpat-bbbbbbbbbbbbbbbb"; // 使用用户 A 的身份创建 issue gitea_issue_create({ title: "Bug 报告", body: "发现一个严重 bug", api_token: userA_token // 使用用户 A 的 token }) // 使用用户 B 的身份创建 issue gitea_issue_create({ title: "功能请求", body: "希望增加导出功能", api_token: userB_token // 使用用户 B 的 token }) ``` ## 高级示例 ### 示例 3:多用户系统 ```typescript // 场景:构建一个多用户的 Gitea 管理平台 class GiteaService { // 根据用户 ID 获取 token async getUserToken(userId: string): Promise<string> { // 从数据库或 secret 管理器获取 return await db.getUserToken(userId); } // 为用户创建 issue async createIssueForUser( userId: string, issueData: { title: string; body: string } ) { const userToken = await this.getUserToken(userId); return gitea_issue_create({ title: issueData.title, body: issueData.body, api_token: userToken // 使用用户的 token }); } // 为用户列出 issues async listIssuesForUser(userId: string) { const userToken = await this.getUserToken(userId); return gitea_issue_list({ api_token: userToken // 使用用户的 token }); } } // 使用示例 const service = new GiteaService(); // 用户 1 创建 issue await service.createIssueForUser("user-1", { title: "我的 issue", body: "这是用户 1 创建的" }); // 用户 2 创建 issue await service.createIssueForUser("user-2", { title: "另一个 issue", body: "这是用户 2 创建的" }); ``` ### 示例 4:权限分离 ```typescript // 场景:不同操作使用不同权限的 token const tokens = { // 只读 token(read scope) readonly: "glpat-readonly-token", // 写入 token(read + write scope) write: "glpat-write-token", // 管理员 token(admin scope) admin: "glpat-admin-token" }; // 查询操作:使用只读 token const issues = await gitea_issue_list({ api_token: tokens.readonly }); const repos = await gitea_repo_list({ api_token: tokens.readonly }); // 创建/修改操作:使用写入 token await gitea_issue_create({ title: "新 issue", body: "描述", api_token: tokens.write }); await gitea_pr_create({ title: "新 PR", head: "feature", base: "main", api_token: tokens.write }); // 危险操作:使用管理员 token await gitea_repo_delete({ owner: "test", repo: "old-project", api_token: tokens.admin // 需要管理员权限 }); await gitea_team_delete({ id: 5, api_token: tokens.admin // 需要管理员权限 }); ``` ### 示例 5:租户隔离(SaaS 场景) ```typescript // 场景:SaaS 平台,每个租户有自己的 Gitea 实例和 token interface Tenant { id: string; name: string; giteaToken: string; } class MultiTenantGiteaService { private tenants: Map<string, Tenant>; constructor() { this.tenants = new Map(); } // 注册租户 registerTenant(tenant: Tenant) { this.tenants.set(tenant.id, tenant); } // 为租户创建仓库 async createRepoForTenant(tenantId: string, repoName: string) { const tenant = this.tenants.get(tenantId); if (!tenant) { throw new Error(`Tenant ${tenantId} not found`); } return gitea_repo_create({ name: repoName, private: true, api_token: tenant.giteaToken // 使用租户的 token }); } // 为租户列出 issues async listIssuesForTenant(tenantId: string) { const tenant = this.tenants.get(tenantId); if (!tenant) { throw new Error(`Tenant ${tenantId} not found`); } return gitea_issue_list({ api_token: tenant.giteaToken // 使用租户的 token }); } } // 使用示例 const service = new MultiTenantGiteaService(); // 注册租户 service.registerTenant({ id: "tenant-a", name: "公司 A", giteaToken: "glpat-tenant-a-token" }); service.registerTenant({ id: "tenant-b", name: "公司 B", giteaToken: "glpat-tenant-b-token" }); // 租户 A 创建仓库 await service.createRepoForTenant("tenant-a", "project-alpha"); // 租户 B 创建仓库 await service.createRepoForTenant("tenant-b", "project-beta"); // 租户之间完全隔离 ``` ### 示例 6:临时授权(短期 Token) ```typescript // 场景:为外部用户提供短期访问权限 class TemporaryAccessService { // 创建短期 token(1 小时有效) async createTemporaryToken(username: string, password: string): Promise<string> { const result = await gitea_token_create({ username: username, password: password, token_name: `temp-token-${Date.now()}`, scopes: ["read:repository", "write:issue"] }); // 1 小时后自动删除 token(需要后台任务支持) setTimeout(async () => { await gitea_token_delete({ username: username, token_id: result.token.id, password: password }); }, 3600000); // 1 小时 return result.token.token; } // 使用临时 token 执行操作 async performTemporaryOperation(tempToken: string) { // 临时用户可以查看 issues const issues = await gitea_issue_list({ api_token: tempToken }); // 临时用户可以创建 issues await gitea_issue_create({ title: "临时用户创建的 issue", body: "这个 token 1 小时后会失效", api_token: tempToken }); // 但不能执行危险操作(token 没有 admin scope) // await gitea_repo_delete({ ... api_token: tempToken }); // 会失败 } } // 使用示例 const service = new TemporaryAccessService(); // 为外部用户创建临时 token const tempToken = await service.createTemporaryToken( "external-user", "their-password" ); // 外部用户使用临时 token 操作 await service.performTemporaryOperation(tempToken); ``` ### 示例 7:测试环境隔离 ```typescript // 场景:同时操作开发、测试、生产环境 const environments = { dev: { baseUrl: "http://dev.gitea.local:3000", token: "glpat-dev-token" }, test: { baseUrl: "http://test.gitea.local:3000", token: "glpat-test-token" }, prod: { baseUrl: "http://gitea.example.com", token: "glpat-prod-token" } }; // 在开发环境创建测试仓库 await gitea_repo_create({ name: "test-repo", description: "开发环境测试", api_token: environments.dev.token }); // 在测试环境创建相同仓库 await gitea_repo_create({ name: "test-repo", description: "测试环境验证", api_token: environments.test.token }); // 在生产环境创建(需要更谨慎) if (confirm("确定要在生产环境创建?")) { await gitea_repo_create({ name: "test-repo", description: "生产环境", api_token: environments.prod.token }); } ``` ### 示例 8:CI/CD 管道 ```typescript // 场景:在 CI/CD 中使用不同的 token class CIPipeline { private ciToken: string; constructor(ciToken: string) { this.ciToken = ciToken; } // 构建完成后创建 Release async createRelease(version: string) { return gitea_release_create({ tag_name: version, name: `Release ${version}`, body: "自动发布", api_token: this.ciToken // CI 专用 token }); } // 部署完成后创建 issue 通知 async notifyDeployment(env: string) { return gitea_issue_create({ title: `部署完成:${env}`, body: `环境 ${env} 已成功部署`, labels: [1, 5], // deployment, success api_token: this.ciToken }); } // 测试失败时创建 issue async reportTestFailure(testName: string, error: string) { return gitea_issue_create({ title: `测试失败:${testName}`, body: `错误信息:${error}`, labels: [2, 7], // test, failure api_token: this.ciToken }); } } // GitHub Actions / GitLab CI 中使用 const pipeline = new CIPipeline(process.env.CI_GITEA_TOKEN); // 在构建流程中调用 await pipeline.createRelease("v1.2.3"); await pipeline.notifyDeployment("production"); ``` ## 完整应用示例 ### 示例 9:Gitea 管理 Dashboard ```typescript // 场景:构建一个 Web Dashboard,管理多个 Gitea 账户 import express from 'express'; const app = express(); // 用户登录后,将他们的 Gitea token 存储在 session 中 app.post('/api/login', async (req, res) => { const { username, password } = req.body; try { // 验证并创建 token const tokenResult = await gitea_token_create({ username: username, password: password, token_name: `dashboard-${Date.now()}` }); // 存储到 session req.session.giteaToken = tokenResult.token.token; req.session.username = username; res.json({ success: true }); } catch (error) { res.status(401).json({ error: "登录失败" }); } }); // 获取用户的仓库列表 app.get('/api/repos', async (req, res) => { const userToken = req.session.giteaToken; if (!userToken) { return res.status(401).json({ error: "未登录" }); } try { const repos = await gitea_repo_list({ api_token: userToken // 使用用户自己的 token }); res.json(repos); } catch (error) { res.status(500).json({ error: "获取失败" }); } }); // 创建 issue app.post('/api/issues', async (req, res) => { const userToken = req.session.giteaToken; const { title, body } = req.body; if (!userToken) { return res.status(401).json({ error: "未登录" }); } try { const issue = await gitea_issue_create({ title, body, api_token: userToken // 使用用户自己的 token }); res.json(issue); } catch (error) { res.status(500).json({ error: "创建失败" }); } }); app.listen(3000); ``` ## 注意事项 ### ✅ 推荐做法 1. **Token 安全存储** ```typescript // 使用环境变量或 secret 管理器 const token = process.env.GITEA_TOKEN; // 不要硬编码 // const token = "glpat-xxxx"; // ❌ 不要这样 ``` 2. **Token 作用域最小化** ```typescript // 只读操作用只读 token await gitea_issue_list({ api_token: readonlyToken }); // 写操作用写 token await gitea_issue_create({ ..., api_token: writeToken }); // 危险操作用管理员 token await gitea_repo_delete({ ..., api_token: adminToken }); ``` 3. **错误处理** ```typescript try { await gitea_issue_create({ title: "Test", api_token: userToken }); } catch (error) { if (error.status === 401) { console.error("Token 无效或已过期"); } else if (error.status === 403) { console.error("Token 权限不足"); } else { console.error("操作失败", error); } } ``` ### ❌ 避免的做法 1. **不要在日志中输出 token** ```typescript // ❌ 不要这样 console.log(`Using token: ${userToken}`); // ✅ 应该这样 console.log("Using user token"); ``` 2. **不要在 URL 中传递 token** ```typescript // ❌ 不要这样 fetch(`/api/repos?token=${userToken}`); // ✅ 应该这样 fetch('/api/repos', { headers: { Authorization: `token ${userToken}` } }); ``` 3. **不要长期存储 token** ```typescript // ❌ 不要这样 localStorage.setItem('gitea_token', token); // ✅ 应该这样(使用 session 或短期存储) sessionStorage.setItem('gitea_token', token); ``` ## 总结 动态 Token 功能让 Gitea MCP 更加灵活和强大: - ✅ 支持多用户场景 - ✅ 支持权限隔离 - ✅ 支持租户隔离 - ✅ 支持临时授权 - ✅ 支持环境隔离 - ✅ 所有 86 个工具自动支持 只需在调用时添加 `api_token` 参数即可!

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/SupenBysz/gitea-mcp-tool'

If you have feedback or need assistance with the MCP directory API, please join our Discord server