Skip to main content
Glama
SkyBlob12

Strava MCP Server

by SkyBlob12

Obtenir l'URL d'autorisation Strava

strava_get_auth_url

Generate the Strava OAuth2 authorization URL to obtain a temporary code. Open the URL in a browser, authorize the app, then copy the 'code' parameter from the redirect URL for token exchange.

Instructions

Génère l'URL OAuth2 Strava. Ouvrir cette URL dans un navigateur, autoriser l'application, puis copier le paramètre 'code' depuis l'URL de redirection et le passer à strava_exchange_token.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The async handler function for the 'strava_get_auth_url' tool. It checks clientId config, starts the OAuth callback server, builds the authorization URL via buildAuthorizationUrl(), and returns the URL to the user.
    async () => {
      if (!config.clientId) {
        return {
          content: [
            {
              type: "text",
              text: "Erreur : STRAVA_CLIENT_ID non configuré. Copie .env.example en .env et renseigne tes credentials.",
            },
          ],
        };
      }
      const redirectUri = config.redirectUri;
      const portMatch = redirectUri.match(/:(\d+)\//);
      const port = portMatch ? parseInt(portMatch[1], 10) : 8080;
      startOAuthCallbackServer(port);
      const url = buildAuthorizationUrl();
      return {
        content: [
          {
            type: "text",
            text: `Ouvre cette URL dans ton navigateur :\n\n${url}\n\nUne fois que tu as autorisé l'application sur Strava, la page affichera "✓ Authentification réussie !" et les tokens seront sauvegardés automatiquement. Tu n'as rien d'autre à faire.`,
          },
        ],
      };
    }
  • The 'strava_get_auth_url' tool is registered inside registerAuthTools() function on line 9 via server.registerTool('strava_get_auth_url', ...). The registration includes the title, description, empty inputSchema, and the handler.
    export function registerAuthTools(server: McpServer): void {
      server.registerTool(
        "strava_get_auth_url",
        {
          title: "Obtenir l'URL d'autorisation Strava",
          description:
            "Génère l'URL OAuth2 Strava. Ouvrir cette URL dans un navigateur, " +
            "autoriser l'application, puis copier le paramètre 'code' depuis " +
            "l'URL de redirection et le passer à strava_exchange_token.",
          inputSchema: z.object({}),
        },
        async () => {
          if (!config.clientId) {
            return {
              content: [
                {
                  type: "text",
                  text: "Erreur : STRAVA_CLIENT_ID non configuré. Copie .env.example en .env et renseigne tes credentials.",
                },
              ],
            };
          }
          const redirectUri = config.redirectUri;
          const portMatch = redirectUri.match(/:(\d+)\//);
          const port = portMatch ? parseInt(portMatch[1], 10) : 8080;
          startOAuthCallbackServer(port);
          const url = buildAuthorizationUrl();
          return {
            content: [
              {
                type: "text",
                text: `Ouvre cette URL dans ton navigateur :\n\n${url}\n\nUne fois que tu as autorisé l'application sur Strava, la page affichera "✓ Authentification réussie !" et les tokens seront sauvegardés automatiquement. Tu n'as rien d'autre à faire.`,
              },
            ],
          };
        }
      );
  • Input schema for the tool: z.object({}) - an empty object, meaning no inputs required.
    inputSchema: z.object({}),
  • buildAuthorizationUrl() helper function that constructs the Strava OAuth2 authorization URL using client_id, redirect_uri, response_type, approval_prompt, and scope parameters.
    export function buildAuthorizationUrl(): string {
      const params = new URLSearchParams({
        client_id: config.clientId,
        redirect_uri: config.redirectUri,
        response_type: "code",
        approval_prompt: "force",
        scope: STRAVA_SCOPES,
      });
      return `${STRAVA_AUTH_URL}?${params.toString()}`;
    }
  • startOAuthCallbackServer() helper function that starts an HTTP server on localhost to handle the OAuth callback from Strava after user authorizes.
    export function startOAuthCallbackServer(port: number): void {
      if (callbackServer) return;
    
      callbackServer = http.createServer(async (req, res) => {
        try {
          const url = new URL(req.url ?? "/", `http://localhost:${port}`);
          if (url.pathname !== "/callback") {
            res.writeHead(404);
            res.end("Not found");
            return;
          }
    
          const error = url.searchParams.get("error");
          if (error) {
            res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
            res.end(
              `<html><body><h1>Erreur Strava</h1><p>${error}</p></body></html>`
            );
            stopOAuthCallbackServer();
            return;
          }
    
          const code = url.searchParams.get("code");
          if (!code) {
            res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
            res.end("<html><body><h1>Paramètre code manquant</h1></body></html>");
            stopOAuthCallbackServer();
            return;
          }
    
          await exchangeCodeForTokens(code);
          res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
          res.end(`
            <html><body style="font-family:sans-serif;text-align:center;padding:60px">
              <h1>✓ Authentification réussie !</h1>
              <p>Tu peux fermer cet onglet et revenir dans Claude.</p>
            </body></html>
          `);
        } catch (err) {
          const msg = err instanceof Error ? err.message : String(err);
          res.writeHead(500, { "Content-Type": "text/html; charset=utf-8" });
          res.end(
            `<html><body><h1>Erreur lors de l'échange du token</h1><p>${msg}</p></body></html>`
          );
        } finally {
          stopOAuthCallbackServer();
        }
      });
    
      callbackServer.listen(port, "127.0.0.1", () => {
        console.error(`OAuth callback server listening on http://localhost:${port}/callback`);
      });
    
      callbackServer.on("error", (err) => {
        console.error("Callback server error:", err.message);
        callbackServer = null;
      });
    }
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations, but description conveys it generates a URL for manual browser interaction. It does not mention any side effects, but generating a URL is inherently safe. Could add that it does not modify any data.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the verb, minimal waste. Every sentence adds value: what it does and how to proceed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no parameters and no output schema, the description provides the essential flow. Could mention that the URL includes client config (likely server-side), but adequate as is.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters, so base score 4. Description adds process context beyond schema (which is empty), but no parameter-level details needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clear verb 'génère' and resource 'URL OAuth2 Strava'. Distinguishes itself from siblings by being the auth URL generator, and logically leads to strava_exchange_token.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly describes the sequence: open in browser, authorize, copy 'code', and pass to strava_exchange_token. Provides clear when-to-use and how-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/SkyBlob12/McpStrava'

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