login
Authenticate with your Money Lover account to access personal finance data and manage transactions through the MCP server.
Instructions
Authenticate using Money Lover credentials to retrieve a JWT token.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| Yes | Money Lover account email | ||
| password | Yes | Money Lover account password |
Implementation Reference
- src/server.js:295-314 (handler)Handler function for the 'login' tool: authenticates via MoneyloverClient.getToken, caches the token, updates env cache if matching, and formats success/error response.async ({ email, password }) => { try { const token = await MoneyloverClient.getToken(email, password); try { await writeToken(email, token); } catch (error) { console.warn('Failed to persist Money Lover token:', error); } const { email: envEmail } = getEnvConfig(); if (email === envEmail && envEmail) { cachedEnvEmail = envEmail; cachedEnvToken = token; cacheLoaded = true; cachedEnvUsesDirectToken = false; } return formatSuccess({ token }); } catch (error) { return formatError(error instanceof Error ? error : new Error(String(error))); } }
- src/server.js:287-293 (schema)Zod schemas defining input (email, password) and output (token) for the 'login' tool.inputSchema: { email: z.string().email().describe('Money Lover account email'), password: z.string().min(1).describe('Money Lover account password') }, outputSchema: { token: z.string() }
- src/server.js:282-315 (registration)Full registration of the 'login' MCP tool on the server, specifying title, description, schemas, and inline handler.server.registerTool( 'login', { title: 'Login to Money Lover', description: 'Authenticate using Money Lover credentials to retrieve a JWT token.', inputSchema: { email: z.string().email().describe('Money Lover account email'), password: z.string().min(1).describe('Money Lover account password') }, outputSchema: { token: z.string() } }, async ({ email, password }) => { try { const token = await MoneyloverClient.getToken(email, password); try { await writeToken(email, token); } catch (error) { console.warn('Failed to persist Money Lover token:', error); } const { email: envEmail } = getEnvConfig(); if (email === envEmail && envEmail) { cachedEnvEmail = envEmail; cachedEnvToken = token; cacheLoaded = true; cachedEnvUsesDirectToken = false; } return formatSuccess({ token }); } catch (error) { return formatError(error instanceof Error ? error : new Error(String(error))); } } );
- src/moneyloverClient.js:66-116 (helper)Core helper: MoneyloverClient.getToken static method implements the login flow by fetching login URL, extracting params, posting credentials to obtain JWT access token.static async getToken(email, password) { const loginResponse = await fetch(LOGIN_URL, { method: 'POST' }); if (!loginResponse.ok) { throw new Error(`Failed to initiate login: HTTP ${loginResponse.status}`); } const loginPayload = await readJson(loginResponse); const requestToken = loginPayload?.data?.request_token; const loginUrl = loginPayload?.data?.login_url; if (!requestToken || !loginUrl) { throw new Error('Login response missing request_token or login_url'); } let clientParam = ''; try { const parsed = new URL(loginUrl); clientParam = parsed.searchParams.get('client') ?? ''; } catch (error) { throw new Error(`Unable to parse login URL: ${error.message}`); } if (!clientParam) { throw new Error('Login URL missing client parameter'); } const form = new URLSearchParams(); form.set('email', ensureString(email, 'email')); form.set('password', ensureString(password, 'password')); const tokenResponse = await fetch(TOKEN_URL, { method: 'POST', headers: { Authorization: `Bearer ${requestToken}`, Client: clientParam, 'Content-Type': 'application/x-www-form-urlencoded' }, body: form.toString() }); if (!tokenResponse.ok) { throw new Error(`Failed to retrieve access token: HTTP ${tokenResponse.status}`); } const tokenPayload = await readJson(tokenResponse); const accessToken = tokenPayload?.access_token; if (!accessToken) { throw new Error('Access token not present in response'); } return accessToken; }