Skip to main content
Glama
noga7

MCP Content Credentials Server

by noga7

read_credentials_url

Extract and display C2PA Content Credentials from files at URLs to verify creator identity, AI generation details, and content authenticity.

Instructions

Read Content Credentials from a file at a URL. USE THIS TOOL when the user provides a URL AND asks questions like: "who made this", "how was this made", "where does this come from", "is this AI", "is this real", "does this have Content Credentials", "what are the c2pa details", or mentions "c2pa" or "Content Credentials". Downloads the file temporarily, checks for embedded C2PA manifests, then cleans up. If the user asks a SPECIFIC question (e.g., "Is this AI?"), answer their question directly using the relevant data, then offer to share more details from the Content Credentials. If the user asks GENERALLY about the file or its credentials, present the information in this order (SKIP sections that have no data): 1) Who this comes from (use BULLET POINTS, prioritize LinkedIn verified identities at the top - OMIT THIS ENTIRE SECTION if no CAWG or personal identity is found), 2) About this content (actions taken - EXCLUDE "c2pa.opened" actions unless specifically requested), 3) About these Content Credentials (signer and timestamp), 4) Validation info (certificate details).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlYesHTTP or HTTPS URL of the file to check for Content Credentials

Implementation Reference

  • Core implementation of readCredentialsFromUrl method - validates URL, downloads file to temporary location, reads credentials using readCredentialsFromFile, and ensures cleanup in finally block
    /** * Read Content Credentials from a URL */ async readCredentialsFromUrl(url: string): Promise<C2PAResult> { logger.info('Reading credentials from URL', { url }); let tempPath: string | null = null; try { // Validate URL validateUrl(url); // Download the file tempPath = await downloadFile(url); // Read credentials from downloaded file const result = await this.readCredentialsFromFile(tempPath); return result; } catch (error: unknown) { logger.error('Failed to read credentials from URL', error, { url }); const errorMessage = error instanceof Error ? error.message : 'Failed to process URL'; return { success: false, hasCredentials: false, error: errorMessage, }; } finally { // Always clean up temporary file if (tempPath) { await safeDelete(tempPath); } } }
  • MCP tool handler for read_credentials_url in stdio transport - validates url parameter, calls c2paService.readCredentialsFromUrl, and formats the result for MCP response
    case 'read_credentials_url': { const params = args as Partial<ReadCredentialsUrlParams>; const { url } = params; if (!url) { throw new Error('Missing required parameter: url'); } logger.debug('Processing read_credentials_url', { url }); const result = await c2paService.readCredentialsFromUrl(url); return { content: [ { type: 'text', text: formatResult(result), }, ], }; }
  • Type definition for ReadCredentialsUrlParams - defines the url parameter interface for the read_credentials_url tool
    /** * Parameters for read_credentials_url tool */ export interface ReadCredentialsUrlParams { url: string; }
  • src/index.ts:76-92 (registration)
    Tool registration for read_credentials_url in stdio transport - defines tool name, description, usage instructions, and inputSchema with required url parameter
    { name: 'read_credentials_url', description: 'Read Content Credentials from a file at a URL. USE THIS TOOL when the user provides a URL AND asks questions like: "who made this", "how was this made", "where does this come from", "is this AI", "is this real", "does this have Content Credentials", "what are the c2pa details", or mentions "c2pa" or "Content Credentials". Downloads the file temporarily, checks for embedded C2PA manifests, then cleans up. ' + 'If the user asks a SPECIFIC question (e.g., "Is this AI?"), answer their question directly using the relevant data, then offer to share more details from the Content Credentials. ' + 'If the user asks GENERALLY about the file or its credentials, present the information in this order (SKIP sections that have no data): 1) Who this comes from (use BULLET POINTS, prioritize LinkedIn verified identities at the top - OMIT THIS ENTIRE SECTION if no CAWG or personal identity is found), 2) About this content (actions taken - EXCLUDE "c2pa.opened" actions unless specifically requested), 3) About these Content Credentials (signer and timestamp), 4) Validation info (certificate details).', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'HTTP or HTTPS URL of the file to check for Content Credentials', }, }, required: ['url'], }, },
  • downloadFile helper function - downloads file from URL to temporary location with timeout handling, HTTP error checking, and streaming pipeline for efficient file transfer
    /** * Download a file from URL to a temporary location * @returns Path to the downloaded temporary file */ export async function downloadFile(url: string): Promise<string> { logger.info('Starting file download', { url }); const tempDir = os.tmpdir(); const fileName = generateTempFileName(url); const tempPath = path.join(tempDir, fileName); try { // Create abort controller for timeout const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), DOWNLOAD_TIMEOUT_MS); const response = await fetch(url, { signal: controller.signal }); clearTimeout(timeoutId); if (!response.ok) { logger.error('Download failed with HTTP error', undefined, { url, status: response.status, statusText: response.statusText, }); throw new DownloadError(url, response.status); } if (!response.body) { logger.error('Download failed: empty response body', undefined, { url }); throw new DownloadError(url); } const fileStream = createWriteStream(tempPath); // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument await pipeline(Readable.fromWeb(response.body as any), fileStream); logger.info('File downloaded successfully', { url, tempPath }); return tempPath; } catch (error) { logger.error('File download failed', error, { url }); if (error instanceof DownloadError || error instanceof DownloadTimeoutError) { throw error; } // Handle abort/timeout if (error instanceof Error && error.name === 'AbortError') { throw new DownloadTimeoutError(url, DOWNLOAD_TIMEOUT_MS); } throw new DownloadError(url); } }
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/noga7/mcp-content-credentials'

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