Debugging FluentCommunity API Integration – Lessons Learned

๐Ÿ”ง Debugging FluentCommunity API Integration

A Complete Guide to Fixing WordPress REST API Proxy Issues

FluentMCP v1.5.4 โ†’ v1.7.0 | November 25-26, 2025

๐Ÿ“Š Project Stats:
15 Versions Released 7 Critical Bugs Fixed 100% Tests Passing 4 Hours Debugging

๐ŸŽฏ Executive Summary

This document chronicles the debugging process for fixing 7 failing FluentCommunity API endpoints in the FluentMCP WordPress plugin. The issues spanned incorrect HTTP methods, wrong parameter names, database table mismatches, and missing plugin version headers.

๐Ÿšจ The Initial Problem

Symptom: 7 out of all FluentCommunity MCP tools were returning errors (400, 404, 422)
Impact: Core functionality (update post, comments CRUD, bulk operations) completely broken
Root Cause: Multiple integration issues between MCP tool schema, WordPress REST API, and FluentCommunity API

Failing Tests

Tool Error Root Cause Fixed In
fc_update_post 404 Not Found Using PUT instead of POST v1.5.6
fc_create_comment 422 Unprocessable Wrong parameter name (message vs comment) v1.5.7
fc_update_comment 400 Bad Request Missing post_id + wrong table name v1.6.9
fc_delete_comment 400 Bad Request Missing post_id + wrong table name v1.6.9
fc_add_space_member 400 Bad Request Direct DB access instead of API v1.5.8
fc_bulk_create_posts 404 Not Found Endpoint not implemented v1.5.9
Plugin Version Shows wrong version Header not updated v1.6.9

๐Ÿ” Detailed Bug Analysis

Bug #1: Update Post – Wrong HTTP Method

Error: 404 Not Found
Endpoint: PUT /fc-manager/v1/posts/{id}

๐ŸŽ“ Key Lesson: Always Check the API Routes File

The Problem: The MCP tool was sending PUT requests, but FluentCommunity’s API routes only registered POST for updates.

Evidence from api.php:

// Line 42: FluentCommunity API routes
Route::post('/{spaceSlug}/feeds/{feedId}', [FeedsController::class, 'patchBySlug']);

The Fix: Changed the plugin route registration to accept POST instead of PUT.

// Before (v1.5.5)
array(
    'methods' => 'PUT',
    'callback' => 'fmcp_rest_update_post',
)

// After (v1.5.6)
array(
    'methods' => 'POST',  // Changed to POST
    'callback' => 'fmcp_rest_update_post',
)

Bug #2: Create Comment – Wrong Parameter Name

Error: 422 Unprocessable Entity
Sent: {"message": "Comment text"}
Expected: {"comment": "Comment text"}

๐ŸŽ“ Key Lesson: API Documentation Can Be Wrong – Check the Controller

The Problem: Official API docs said to use message parameter, but the controller expected comment.

Evidence from CommentsController.php:

// Line 165: validateCommentText method
protected function validateCommentText($request)
{
    $comment = $request->get('comment');  // Expects 'comment', not 'message'!
    
    if (!$comment) {
        return new \WP_Error('invalid_comment', __('Comment text is required'));
    }
    // ...
}

The Fix: Added parameter mapping in the proxy function to convert message โ†’ comment.

// Added to fmcp_map_parameters_for_fluentcommunity()
if (strpos($endpoint, 'comments') !== false) {
    if (isset($params['message']) && !isset($params['comment'])) {
        $params['comment'] = $params['message'];
        unset($params['message']);
    }
}

Bug #3 & #4: Update/Delete Comment – Multiple Issues

Error: 400 Bad Request then 404 Not Found
Issues:
  • MCP tool doesn’t send post_id parameter
  • Wrong database table name (fcom_comments vs fcom_post_comments)
  • Route registered for PUT but MCP sends POST

๐ŸŽ“ Key Lesson: Use Debug Logging to See Actual Request Data

The Problem: We were guessing what parameters the MCP tool was sending. Adding debug logging revealed the truth.

Debug Output (v1.6.7):

=== UPDATE COMMENT - INCOMING REQUEST ===
All params: {"id":"5","message":"Test"}
Route: /fc-manager/v1/comments/5
Method: PUT
URL params: {"id":"5"}
Body params: {}
Extracted comment_id: 5
Extracted post_id:   // EMPTY! MCP tool doesn't send it!

Database Error:

WordPress database error Table 'iwpdfd6_fcom_comments' doesn't exist
// Should be 'fcom_post_comments'!

The Fix (3 parts):

1. Auto-lookup post_id from database:

if (!$post_id) {
    global $wpdb;
    $table = $wpdb->prefix . 'fcom_post_comments';  // Correct table name
    $post_id = $wpdb->get_var($wpdb->prepare(
        "SELECT post_id FROM $table WHERE id = %d",
        $comment_id
    ));
    
    if (!$post_id) {
        return new WP_Error('comment_not_found', 'Comment not found', array('status' => 404));
    }
}

2. Accept both PUT and POST methods:

register_rest_route($namespace, '/comments/(?P\d+)', array(
    array(
        'methods' => array('PUT', 'POST'),  // Accept both
        'callback' => 'fmcp_rest_update_comment',
    ),
));

3. Use the proxy function (not manual request building):

// Simple and clean - proxy handles everything
return fmcp_proxy_to_fluentcommunity(
    $request, 
    'feeds/' . $post_id . '/comments/' . $comment_id, 
    'POST'
);

Bug #5: Add Space Member – Wrong Approach

Error: 400 Bad Request
Issue: Direct database INSERT instead of using FluentCommunity API

๐ŸŽ“ Key Lesson: Always Use the API, Never Direct Database Access

The Problem: The function was doing direct database inserts, bypassing FluentCommunity’s validation and hooks.

Before (v1.5.7):

// BAD: Direct database access
global $wpdb;
$table = $wpdb->prefix . 'fcom_space_user';
$wpdb->insert($table, array(
    'space_id' => $space_id,
    'user_id' => $user_id,
    'role' => $role
));

After (v1.5.8):

// GOOD: Use the API endpoint
$slug = fmcp_get_space_slug_by_id($space_id);
return fmcp_proxy_to_fluentcommunity(
    $request, 
    'spaces/' . $slug . '/members', 
    'POST'
);

Bug #6: Bulk Create Posts – Missing Endpoint

Error: 404 Not Found
Issue: Endpoint /posts/bulk was never registered
The Fix: Implemented the missing endpoint with proper iteration.
// Register the route
register_rest_route($namespace, '/posts/bulk', array(
    'methods' => 'POST',
    'callback' => 'fmcp_rest_bulk_create_posts',
));

// Implementation
function fmcp_rest_bulk_create_posts($request) {
    $posts = $request->get_param('posts');
    $results = array();
    
    foreach ($posts as $post_data) {
        $post_request = new WP_REST_Request('POST', '/fc-manager/v1/posts');
        foreach ($post_data as $key => $value) {
            $post_request->set_param($key, $value);
        }
        $results[] = fmcp_rest_create_post($post_request);
    }
    
    return rest_ensure_response($results);
}

Bug #7: Plugin Version Not Updating

Error: WordPress shows v1.6.2 when v1.6.9 is installed
Issue: Plugin header version wasn’t being updated

๐ŸŽ“ Key Lesson: Update BOTH the VERSION File AND Plugin Header

The Problem: We were updating the VERSION file but not the plugin header comment.

What WordPress Reads:

/**
 * Plugin Name: FluentMCP
 * Version: 1.6.2  // โ† WordPress reads THIS, not the VERSION file!
 * Author: 1WD LLC
 */

The Fix: Update both locations in every release.

// 1. Update plugin header
sed -i 's/Version: 1.6.9/Version: 1.7.0/' fluent-mcp.php

// 2. Update VERSION file
echo "1.7.0" > VERSION

// 3. Create release
zip -r fluent-mcp-v1.7.0.zip fluent-mcp.php VERSION CHANGELOG.md

๐Ÿ“‹ Version History Timeline

v1.5.4 Initial Bug Report – 7 tests failing
v1.5.5 Space GET/UPDATE Fix – Implemented slug lookup
v1.5.6 Post Update Fix – Changed PUT to POST
v1.5.7 Comment Create Fix – Added messageโ†’comment mapping
v1.5.8 Space Member Fix – Switched to API from direct DB
v1.5.9 Bulk Posts Fix – Implemented missing endpoint
v1.6.0-v1.6.8 Comment Update/Delete Attempts – Multiple iterations debugging
v1.6.9 Comment Fix Complete – Correct table name + auto post_id lookup
v1.7.0 Production Release – All tests passing, debug logging removed

๐Ÿ› ๏ธ Debugging Methodology That Worked

1. Create a Test Sandbox Script

Instead of creating 15 plugin versions, we should have created a standalone test script first:

// test-api.php - Direct API testing
$auth = base64_encode("username:password");
$context = stream_context_create([
    'http' => [
        'method' => 'POST',
        'header' => "Authorization: Basic $auth\r\nContent-Type: application/json\r\n",
        'content' => json_encode(['comment' => 'Test'])
    ]
]);
$response = file_get_contents("https://site.com/wp-json/fluent-community/v2/feeds/56/comments/5", false, $context);
echo $response;

2. Add Comprehensive Debug Logging

Log EVERYTHING about the incoming request:

error_log('=== DEBUG ===');
error_log('All params: ' . json_encode($request->get_params()));
error_log('Method: ' . $request->get_method());
error_log('Route: ' . $request->get_route());
error_log('Body: ' . json_encode($request->get_body_params()));
error_log('URL params: ' . json_encode($request->get_url_params()));

3. Test Directly Against the API

Use PowerShell/curl to bypass the plugin and test the actual FluentCommunity API:

# PowerShell direct test
$auth = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("user:pass"))
Invoke-RestMethod -Uri "https://site.com/wp-json/fluent-community/v2/feeds/56/comments/5" `
    -Method Post `
    -Headers @{Authorization="Basic $auth"} `
    -Body (@{comment="Test"} | ConvertTo-Json) `
    -ContentType "application/json"

4. Read the Source Code, Not Just the Docs

The official API documentation was WRONG about parameter names. Always verify in the controller:

  • โœ… Check api.php for routes and HTTP methods
  • โœ… Check Controller.php for parameter names and validation
  • โœ… Check Migrations/ for database table names
  • โŒ Don’t trust documentation alone

๐ŸŽฏ Critical Lessons Learned

WordPress REST API Best Practices

  1. Use set_body_params() for POST/PUT/PATCH: Just set_param() isn’t enough for body parameters
  2. Accept multiple HTTP methods: Use array('PUT', 'POST') for flexibility
  3. Always use the proxy pattern: Don’t build WP_REST_Request manually
  4. Update plugin header version: WordPress reads the comment, not the VERSION file

FluentCommunity API Quirks

  1. Comments use comment not message: Despite what the docs say
  2. Table name is fcom_post_comments: Not fcom_comments
  3. Updates use POST not PUT: Check api.php routes
  4. Spaces need slugs not IDs: For most operations

Debugging Strategy

  1. Create test sandbox FIRST: Don’t iterate on production plugin
  2. Add debug logging early: See actual request data
  3. Test API directly: Use PowerShell/curl to isolate issues
  4. Read source code: Controllers > Documentation
  5. Use the MCP connection: Test tools directly from the agent

๐Ÿ“Š Final Results

โœ… All Tests Passing (v1.7.0)

Tool Status Test Result
fc_update_post โœ… Working POST method, correct parameters
fc_create_comment โœ… Working messageโ†’comment mapping
fc_update_comment โœ… Working Auto post_id lookup, correct table
fc_delete_comment โœ… Working Auto post_id lookup, correct table
fc_add_space_member โœ… Working Using API endpoint
fc_bulk_create_posts โœ… Working Endpoint implemented
fc_list_comments โœ… Working Always worked

๐Ÿ”ฎ Future Recommendations

  1. Create automated tests: PHPUnit tests for each endpoint
  2. Add parameter validation: Validate before proxying to FluentCommunity
  3. Implement caching: Cache slug lookups to reduce DB queries
  4. Add rate limiting: Protect against API abuse
  5. Better error messages: Return specific error details to users
  6. Version check script: Automate checking both header and VERSION file match

๐Ÿ“š Code Snippets Library

Correct Way to Proxy to FluentCommunity

function fmcp_rest_update_comment($request) {
    $comment_id = $request->get_param('id') ?: $request->get_param('comment_id');
    $post_id = $request->get_param('post_id');
    
    // Auto-lookup post_id if not provided
    if (!$post_id) {
        global $wpdb;
        $table = $wpdb->prefix . 'fcom_post_comments';
        $post_id = $wpdb->get_var($wpdb->prepare(
            "SELECT post_id FROM $table WHERE id = %d",
            $comment_id
        ));
        
        if (!$post_id) {
            return new WP_Error('comment_not_found', 'Comment not found', array('status' => 404));
        }
    }
    
    // Use the proxy - it handles everything
    return fmcp_proxy_to_fluentcommunity(
        $request, 
        'feeds/' . $post_id . '/comments/' . $comment_id, 
        'POST'
    );
}

Parameter Mapping Function

function fmcp_map_parameters_for_fluentcommunity($params, $endpoint, $method = 'GET') {
    // Map 'message' to 'comment' for comment endpoints
    if (strpos($endpoint, 'comments') !== false) {
        if (isset($params['message']) && !isset($params['comment'])) {
            $params['comment'] = $params['message'];
            unset($params['message']);
        }
    }
    
    // Wrap parameters for space updates
    if ($endpoint === 'spaces' && $method === 'PUT' && !empty($params)) {
        $params = array('data' => $params);
    }
    
    return $params;
}

Proper Route Registration

register_rest_route($namespace, '/comments/(?P\d+)', array(
    array(
        'methods' => array('PUT', 'POST'),  // Accept both methods
        'callback' => 'fmcp_rest_update_comment',
        'permission_callback' => 'fmcp_rest_permission_check'
    ),
    array(
        'methods' => 'DELETE',
        'callback' => 'fmcp_rest_delete_comment',
        'permission_callback' => 'fmcp_rest_permission_check'
    )
));

๐Ÿ™ Acknowledgments

This debugging session was a collaborative effort that required:

  • โœ… Reading FluentCommunity source code
  • โœ… Testing with PowerShell direct API calls
  • โœ… Using MCP tools for live testing
  • โœ… Extensive debug logging
  • โœ… Patience through 15 version iterations

Key Takeaway: When debugging API integrations, always verify your assumptions by testing directly against the API and reading the source code. Documentation can be outdated or wrong.

FluentMCP v1.7.0 – All Systems Operational โœ…

November 25-26, 2025 | Debugging Session

Created by Claude Sonnet 4.5 | For: FluentMCP Development Team