Skip to main content
Glama
WonderCV

ClawHire MCP

by WonderCV

list_jobs

View published job listings with application statistics to monitor hiring progress and manage recruitment workflows.

Instructions

查看已发布的职位列表及申请统计。

返回信息:

  • 职位基本信息(标题、城市、薪资)

  • 申请数量(各职位的投递数)

  • 职位状态(已发布/已过期等)

可用于:

  • 了解各职位的招聘进展

  • 决定是否需要刷新或关闭某职位

  • 快速跳转到特定职位的候选人搜索

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
session_idYes会话 ID,从 register_company 获取
statusNo职位状态过滤:0=草稿, 1=已发布, 2=已过期, 3=已下线
pageNo页码,默认1
page_sizeNo每页数量,默认20,最大50

Implementation Reference

  • The main execute handler for the list_jobs tool. Validates the session, calls the listJobs API, formats the job data with status text and salary ranges, and returns a structured response with job listings, pagination info, and usage stats.
    async execute(input: Input) {
      // Validate session
      const session = getSession(input.session_id);
      if (!session) {
        return {
          content: [
            {
              type: 'text',
              text: JSON.stringify({
                error: {
                  code: 'INVALID_SESSION',
                  message: '会话已过期或无效,请重新调用 register_company',
                },
              }, null, 2),
            },
          ],
          isError: true,
        };
      }
    
      try {
        const response = await listJobs({
          session_id: input.session_id,
          status: input.status,
          page: input.page,
          page_size: input.page_size,
        });
    
        const { data } = response;
        const tierConfig = getTierConfig(session);
    
        // Format jobs for display
        const formattedJobs = data.jobs.map(job => ({
          job_token: job.token,
          job_post: job.job_post,
          city_names: job.city_names,
          salary_range: job.salary_min && job.salary_max
            ? `¥${(job.salary_min / 1000).toFixed(0)}k-${(job.salary_max / 1000).toFixed(0)}k`
            : '薪资面议',
          status: job.status,
          status_text: statusMap[job.status] || '未知',
          application_count: job.application_count,
          created_at: job.created_at,
        }));
    
        // Calculate page-level stats (note: these are for current page only, not global totals)
        const pageApplications = data.jobs.reduce((sum, job) => sum + job.application_count, 0);
        // Note: For accurate global totals, backend should return aggregated metrics
        // This is a known limitation - page 2+ will show different "active_jobs" counts
    
        return {
          content: [
            {
              type: 'text',
              text: JSON.stringify({
                data: {
                  jobs: formattedJobs,
                  total: data.total,
                  page: data.page,
                  page_size: data.page_size,
                  summary: {
                    // These stats reflect current page only due to pagination
                    // Backend enhancement needed for global totals across all pages
                    active_jobs_on_page: data.jobs.filter(j => j.status === 1).length,
                    applications_on_page: pageApplications,
                    total_jobs_global: data.total,
                    note: '职位统计反映当前页数据。Backend enhancement needed for global totals (see KnownIssues.md #4)',
                  },
                },
                access: {
                  tier: session.tier,
                  daily_limits: tierConfig.daily_limits,
                  jobs_remaining_today: tierConfig.daily_limits.active_jobs - session.daily_usage.jobs_posted,
                },
                meta: {
                  session_id: session.session_id,
                },
                next_steps: data.jobs.length > 0 
                  ? [
                      '调用 search_candidates 搜索匹配的候选人',
                      '调用 list_applications 查看最新投递',
                    ]
                  : [
                      '还没有发布职位,调用 post_job 发布第一个职位',
                    ],
              }, null, 2),
            },
          ],
          isError: false,
        };
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : '获取职位列表失败';
        return {
          content: [
            {
              type: 'text',
              text: JSON.stringify({
                error: {
                  code: 'LIST_JOBS_FAILED',
                  message: errorMessage,
                },
              }, null, 2),
            },
          ],
          isError: true,
        };
      }
    },
  • Zod input schema definition for list_jobs tool. Defines validation for session_id (required string), status (optional int 0-4), page (optional positive int), and page_size (optional positive int max 50).
    const inputSchema = z.object({
      session_id: z.string()
        .describe('会话 ID,从 register_company 获取'),
      
      status: z.number()
        .int()
        .min(0)
        .max(4)
        .optional()
        .describe('职位状态过滤:0=草稿, 1=已发布, 2=已过期, 3=已下线'),
      
      page: z.number()
        .int()
        .positive()
        .optional()
        .describe('页码,默认1'),
      
      page_size: z.number()
        .int()
        .positive()
        .max(50)
        .optional()
        .describe('每页数量,默认20,最大50'),
    });
    
    type Input = z.infer<typeof inputSchema>;
  • Registration of listJobsTool in the allTools array. The tool is imported on line 30 and exported, then added to the registry array on line 52.
    // Tool registry for server initialization
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    export const allTools: Tool<any>[] = [
      registerCompanyTool,
      postJobTool,
      listJobsTool,
      searchCandidatesTool,
      viewCandidateTool,
      listApplicationsTool,
      requestOutreachTool,
    ];
  • TypeScript interfaces (ListJobsInput, ListJobsOutput) and the listJobs async function that makes the API request to fetch jobs from the backend with query parameters.
    export interface ListJobsInput {
      session_id: string;
      status?: number;
      page?: number;
      page_size?: number;
    }
    
    export interface ListJobsOutput {
      jobs: JobWithStats[];
      total: number;
      page: number;
      page_size: number;
    }
    
    export async function listJobs(
      input: ListJobsInput
    ): Promise<ApiResponse<ListJobsOutput>> {
      const params = new URLSearchParams();
      params.append('session_id', input.session_id);
      if (input.status !== undefined) params.append('status', input.status.toString());
      if (input.page !== undefined) params.append('page', input.page.toString());
      if (input.page_size !== undefined) params.append('page_size', input.page_size.toString());
    
      return apiRequest(`/jobs?${params.toString()}`, {
        method: 'GET',
      });
    }

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/WonderCV/clawhire-mcp'

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