Skip to main content
Glama

REST-to-Postman MCP

by runninghare
postman.ts9.01 kB
import axios from 'axios'; import * as dotenv from 'dotenv'; import * as fs from 'fs'; import * as path from 'path'; import type { PostmanCollection, PostmanCollectionResponse, PostmanEnvironment, PostmanWorkspaceResponse, PostmanCollectionsResponse, PostmanRequest, EnvValue, PostmanCollectionRequest } from './types'; dotenv.config(); export async function getEnvironment(environmentName: string, postmanApiKey?: string, workspaceId?: string) { const apiKey = postmanApiKey || process.env.POSTMAN_API_KEY; const activeWorkspaceId = workspaceId || process.env.POSTMAN_ACTIVE_WORKSPACE_ID; const workspaceResponse = await axios({ method: 'get', url: `https://api.getpostman.com/workspaces/${activeWorkspaceId}`, headers: { 'X-Api-Key': apiKey } }); const workspaceData = workspaceResponse.data as PostmanWorkspaceResponse; const environment = workspaceData.workspace.environments?.find( env => env.name === environmentName ); if (!environment) { throw new Error(`Environment ${environmentName} not found`); } const response = await axios({ method: 'get', url: `https://api.getpostman.com/environments/${environment.id}`, headers: { 'X-Api-Key': apiKey, 'Content-Type': 'application/json' } }); return response.data.environment as PostmanEnvironment; } export async function pushEnvironment(environmentName: string, envVars: Record<string, string>, postmanApiKey?: string, workspaceId?: string): Promise<void> { try { const apiKey = postmanApiKey || process.env.POSTMAN_API_KEY; const activeWorkspaceId = workspaceId || process.env.POSTMAN_ACTIVE_WORKSPACE_ID; // Read all environment variables except POSTMAN_API_KEY and POSTMAN_ACTIVE_WORKSPACE_ID const envValues: EnvValue[] = []; for (const [key, value] of Object.entries(envVars)) { envValues.push({ key, value, enabled: true, type: key.includes('token') ? 'secret' : 'default' }); } // Check if environment already exists const workspaceResponse = await axios({ method: 'get', url: `https://api.getpostman.com/workspaces/${activeWorkspaceId}`, headers: { 'X-Api-Key': apiKey } }); const workspaceData = workspaceResponse.data as PostmanWorkspaceResponse; const existingEnvironment = workspaceData.workspace.environments?.find( env => env.name === environmentName ); // Prepare the environment data const environmentData = { environment: { name: environmentName, values: envValues } }; let response; if (existingEnvironment) { response = await axios({ method: 'put', url: `https://api.getpostman.com/environments/${existingEnvironment.id}`, headers: { 'X-Api-Key': apiKey, 'Content-Type': 'application/json' }, data: environmentData }); } else { response = await axios({ method: 'post', url: 'https://api.getpostman.com/environments', headers: { 'X-Api-Key': apiKey, 'Content-Type': 'application/json' }, data: { ...environmentData, workspace: activeWorkspaceId } }); } } catch (error) { throw error; } } export async function getCollection(collectionName: string, postmanApiKey?: string, workspaceId?: string) { const apiKey = postmanApiKey || process.env.POSTMAN_API_KEY; const activeWorkspaceId = workspaceId || process.env.POSTMAN_ACTIVE_WORKSPACE_ID; const workspaceResponse = await axios({ method: 'get', url: `https://api.getpostman.com/workspaces/${activeWorkspaceId}`, headers: { 'X-Api-Key': apiKey } }); const workspaceData = workspaceResponse.data as PostmanWorkspaceResponse; const collection = workspaceData.workspace.collections?.find( collection => collection.name === collectionName ); if (!collection) { throw new Error(`Collection ${collectionName} not found`); } const collectionResponse = await axios({ method: 'get', url: `https://api.getpostman.com/collections/${collection.id}`, headers: { 'X-Api-Key': apiKey } }); return collectionResponse.data.collection as PostmanCollection; } export async function pushCollection(collectionRequest: PostmanCollectionRequest, postmanApiKey?: string, workspaceId?: string): Promise<void> { try { const apiKey = postmanApiKey || process.env.POSTMAN_API_KEY; const activeWorkspaceId = workspaceId || process.env.POSTMAN_ACTIVE_WORKSPACE_ID; // Create collection container const containerRequestBody = { collection: collectionRequest, workspace: activeWorkspaceId }; // Check if collection already exists try { const workspaceResponse = await axios({ method: 'get', url: `https://api.getpostman.com/workspaces/${activeWorkspaceId}`, headers: { 'X-Api-Key': apiKey } }); const workspaceData = workspaceResponse.data as PostmanWorkspaceResponse; var existingCollection = workspaceData.workspace.collections?.find( collection => collection.name === collectionRequest.info.name ); } catch (error) { console.error('Error in pushCollection:', error); } let response; if (existingCollection) { // Reuse getCollection to fetch existing collection data const existingCollectionData = await getCollection(collectionRequest.info.name, apiKey, activeWorkspaceId); // Helper function to normalize request for comparison const normalizeRequest = (request: PostmanRequest) => { const normalized = JSON.parse(JSON.stringify(request)); // Remove id and uid delete normalized.id; delete normalized.uid; // Remove empty arrays if (normalized.response && normalized.response.length === 0) delete normalized.response; if (normalized.request?.header && normalized.request.header.length === 0) delete normalized.request.header; return JSON.stringify(normalized); }; // Deduplicate items while merging const existingItems = existingCollectionData.item || []; const newItems = collectionRequest.item || []; const uniqueItems = [...existingItems]; for (const newItem of newItems) { const normalizedNew = normalizeRequest(newItem); const isDuplicate = uniqueItems.some(existingItem => normalizeRequest(existingItem) === normalizedNew ); if (!isDuplicate) { uniqueItems.push(newItem); } } // Merge the collections const mergedCollection: PostmanCollectionRequest = { info: { ...existingCollectionData.info, ...collectionRequest.info }, auth: collectionRequest.auth || existingCollectionData.auth, item: uniqueItems, event: [...(existingCollectionData.event || []), ...(collectionRequest.event || [])] }; // remove `auth` if it is empty if (mergedCollection.auth && Object.keys(mergedCollection.auth).length === 0) { delete mergedCollection.auth; } // console.log(JSON.stringify(mergedCollection, null, 2)); // Update with merged data response = await axios({ method: 'put', url: `https://api.getpostman.com/collections/${existingCollection.id}`, headers: { 'X-Api-Key': apiKey, 'Content-Type': 'application/json' }, data: { collection: mergedCollection, workspace: activeWorkspaceId } }); } else { // Remove `auth` if it is empty if (containerRequestBody.collection.auth && Object.keys(containerRequestBody.collection.auth).length === 0) { delete containerRequestBody.collection.auth; } response = await axios({ method: 'post', url: 'https://api.getpostman.com/collections', headers: { 'X-Api-Key': apiKey, 'Content-Type': 'application/json' }, data: containerRequestBody }); } } catch (error) { console.error('Error in pushCollection:', error); throw error; } }

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/runninghare/rest-to-postman'

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